* [dpdk-dev] [RFC PATCH v1] rte: add bit-rate metrics to xstats @ 2016-08-24 14:58 Remy Horton 2016-08-26 13:28 ` Pattan, Reshma ` (2 more replies) 0 siblings, 3 replies; 115+ messages in thread From: Remy Horton @ 2016-08-24 14:58 UTC (permalink / raw) To: thomas.monjalon; +Cc: dev This patch adds peak and average data-rate metrics to the extended statistics. The intervals used to generate the statistics are controlled by any application wishing to make use of these metrics. Signed-off-by: Remy Horton <remy.horton@intel.com> --- doc/guides/rel_notes/release_16_11.rst | 5 ++ lib/librte_ether/rte_ethdev.c | 107 ++++++++++++++++++++++++++++++++- lib/librte_ether/rte_ethdev.h | 41 +++++++++++++ lib/librte_ether/rte_ether_version.map | 6 ++ 4 files changed, 157 insertions(+), 2 deletions(-) diff --git a/doc/guides/rel_notes/release_16_11.rst b/doc/guides/rel_notes/release_16_11.rst index 0b9022d..b319292 100644 --- a/doc/guides/rel_notes/release_16_11.rst +++ b/doc/guides/rel_notes/release_16_11.rst @@ -36,6 +36,11 @@ New Features This section is a comment. Make sure to start the actual text at the margin. + * **Added data-rate metrics to the extended statistics.** + + Adds peak and average incoming and outgoing data-rate metrics to the + extended statistics, the calculation of which is controlled by + applications that wish for these to be derived. Resolved Issues --------------- diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index f62a9ec..71549b4 100644 --- a/lib/librte_ether/rte_ethdev.c +++ b/lib/librte_ether/rte_ethdev.c @@ -101,6 +101,7 @@ static const struct rte_eth_xstats_name_off rte_stats_strings[] = { }; #define RTE_NB_STATS (sizeof(rte_stats_strings) / sizeof(rte_stats_strings[0])) +#define RTE_NB_DEV_STATS 4 static const struct rte_eth_xstats_name_off rte_rxq_stats_strings[] = { {"packets", offsetof(struct rte_eth_stats, q_ipackets)}, @@ -1499,6 +1500,7 @@ void rte_eth_stats_reset(uint8_t port_id) { struct rte_eth_dev *dev; + struct rte_eth_dev_stats *dev_stats; RTE_ETH_VALID_PORTID_OR_RET(port_id); dev = &rte_eth_devices[port_id]; @@ -1506,6 +1508,19 @@ rte_eth_stats_reset(uint8_t port_id) RTE_FUNC_PTR_OR_RET(*dev->dev_ops->stats_reset); (*dev->dev_ops->stats_reset)(dev); dev->data->rx_mbuf_alloc_failed = 0; + + /* Clear device running stat counts */ + dev_stats = &dev->data->stats; + memset(dev_stats->list_ibuckets, 0, + sizeof(uint64_t) * dev_stats->cnt_buckets); + memset(dev_stats->list_obuckets, 0, + sizeof(uint64_t) * dev_stats->cnt_buckets); + dev_stats->last_ibytes = 0; + dev_stats->last_obytes = 0; + dev_stats->peak_ibytes = 0; + dev_stats->peak_obytes = 0; + dev_stats->total_ibytes = 0; + dev_stats->total_obytes = 0; } static int @@ -1522,7 +1537,7 @@ get_xstats_count(uint8_t port_id) return count; } else count = 0; - count += RTE_NB_STATS; + count += RTE_NB_STATS + RTE_NB_DEV_STATS; count += dev->data->nb_rx_queues * RTE_NB_RXQ_STATS; count += dev->data->nb_tx_queues * RTE_NB_TXQ_STATS; return count; @@ -1574,6 +1589,19 @@ rte_eth_xstats_get_names(uint8_t port_id, } } + snprintf(xstats_names[cnt_used_entries++].name, + sizeof(xstats_names[0].name), + "tx_peak_bytes"); + snprintf(xstats_names[cnt_used_entries++].name, + sizeof(xstats_names[0].name), + "tx_mean_bytes"); + snprintf(xstats_names[cnt_used_entries++].name, + sizeof(xstats_names[0].name), + "rx_peak_bytes"); + snprintf(xstats_names[cnt_used_entries++].name, + sizeof(xstats_names[0].name), + "rx_mean_bytes"); + if (dev->dev_ops->xstats_get_names != NULL) { /* If there are any driver-specific xstats, append them * to end of list. @@ -1600,14 +1628,16 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstat *xstats, unsigned count = 0, i, q; signed xcount = 0; uint64_t val, *stats_ptr; + struct rte_eth_dev_stats *dev_stats; RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL); dev = &rte_eth_devices[port_id]; + dev_stats = &dev->data->stats; /* Return generic statistics */ count = RTE_NB_STATS + (dev->data->nb_rx_queues * RTE_NB_RXQ_STATS) + - (dev->data->nb_tx_queues * RTE_NB_TXQ_STATS); + (dev->data->nb_tx_queues * RTE_NB_TXQ_STATS) + RTE_NB_DEV_STATS; /* implemented by the driver */ if (dev->dev_ops->xstats_get != NULL) { @@ -1659,12 +1689,85 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstat *xstats, } } + xstats[count++].value = dev_stats->peak_obytes; + xstats[count++].value = + dev_stats->total_obytes / dev_stats->cnt_buckets; + xstats[count++].value = dev_stats->peak_ibytes; + xstats[count++].value = + dev_stats->total_ibytes / dev_stats->cnt_buckets; + for (i = 0; i < count + xcount; i++) xstats[i].id = i; return count + xcount; } +int +rte_eth_dev_stats_init(uint8_t port_id, uint32_t cnt_buckets) +{ + struct rte_eth_dev *dev; + struct rte_eth_dev_stats *stats; + + RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL); + dev = &rte_eth_devices[port_id]; + stats = &dev->data->stats; + + memset(stats, 0, sizeof(struct rte_eth_dev_stats)); + stats->list_ibuckets = rte_zmalloc( + NULL, sizeof(uint64_t) * cnt_buckets, 0); + stats->list_obuckets = rte_zmalloc( + NULL, sizeof(uint64_t) * cnt_buckets, 0); + if (stats->list_ibuckets == NULL || stats->list_obuckets == NULL) + return -ENOMEM; + stats->cnt_buckets = cnt_buckets; + return 0; +} + +int +rte_eth_dev_stats_calc(uint8_t port_id) +{ + struct rte_eth_dev *dev; + uint64_t *metric; + uint64_t cnt_bytes_in_bucket; + struct rte_eth_dev_stats *stats; + struct rte_eth_stats eth_stats; + unsigned ret_code; + + RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL); + dev = &rte_eth_devices[port_id]; + stats = &dev->data->stats; + + ret_code = rte_eth_stats_get(port_id, ð_stats); + if (ret_code != 0) + return ret_code; + + /* tx_good_bytes */ + metric = RTE_PTR_ADD(ð_stats, rte_stats_strings[3].offset); + cnt_bytes_in_bucket = *metric - stats->last_obytes; + stats->last_obytes = *metric; + if (cnt_bytes_in_bucket > stats->peak_obytes) + stats->peak_obytes = cnt_bytes_in_bucket; + stats->total_obytes -= stats->list_obuckets[stats->next_bucket]; + stats->total_obytes += cnt_bytes_in_bucket; + stats->list_obuckets[stats->next_bucket] = cnt_bytes_in_bucket; + + /* rx_good_bytes */ + metric = RTE_PTR_ADD(ð_stats, rte_stats_strings[2].offset); + cnt_bytes_in_bucket = *metric - stats->last_ibytes; + stats->last_ibytes = *metric; + if (cnt_bytes_in_bucket > stats->peak_ibytes) + stats->peak_ibytes = cnt_bytes_in_bucket; + stats->total_ibytes -= stats->list_ibuckets[stats->next_bucket]; + stats->total_ibytes += cnt_bytes_in_bucket; + stats->list_ibuckets[stats->next_bucket] = cnt_bytes_in_bucket; + + /* index wraparound */ + if (++stats->next_bucket == stats->cnt_buckets) + stats->next_bucket = 0; + + return 0; +} + /* reset ethdev extended statistics */ void rte_eth_xstats_reset(uint8_t port_id) diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h index b0fe033..4b1b47b 100644 --- a/lib/librte_ether/rte_ethdev.h +++ b/lib/librte_ether/rte_ethdev.h @@ -1656,6 +1656,19 @@ struct rte_eth_dev_sriov { #define RTE_ETH_NAME_MAX_LEN (32) +struct rte_eth_dev_stats { + uint64_t *list_ibuckets; + uint64_t *list_obuckets; + uint32_t cnt_buckets; + uint32_t next_bucket; + uint64_t last_ibytes; + uint64_t last_obytes; + uint64_t peak_ibytes; + uint64_t peak_obytes; + uint64_t total_ibytes; + uint64_t total_obytes; +}; + /** * @internal * The data part, with no function pointers, associated with each ethernet device. @@ -1670,6 +1683,7 @@ struct rte_eth_dev_data { void **tx_queues; /**< Array of pointers to TX queues. */ uint16_t nb_rx_queues; /**< Number of RX queues. */ uint16_t nb_tx_queues; /**< Number of TX queues. */ + struct rte_eth_dev_stats stats; /**< Device stats metrics */ struct rte_eth_dev_sriov sriov; /**< SRIOV data */ @@ -2328,6 +2342,33 @@ int rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstat *xstats, unsigned n); /** + * Initialise device statistics. + * + * @param port_id + * The port identifier of the Ethernet device + * @param cnt_buckets + * Number of sampling buckets within sampling window. + * @return + * - Zero on success. + * - Negative value on error. + */ +int rte_eth_dev_stats_init(uint8_t port_id, uint32_t cnt_buckets); + +/** + * Calculate device statistics. + * This function need to be called periodically. The time between each + * invocation is the sampling period of an individual time bucket within + * the sampling window. + * + * @param port_id + * The port identifier of the Ethernet device + * @return + * - Zero on success. + * - Negative value on error. + */ +int rte_eth_dev_stats_calc(uint8_t port_id); + +/** * Reset extended statistics of an Ethernet device. * * @param port_id diff --git a/lib/librte_ether/rte_ether_version.map b/lib/librte_ether/rte_ether_version.map index 45ddf44..bb7d1cf 100644 --- a/lib/librte_ether/rte_ether_version.map +++ b/lib/librte_ether/rte_ether_version.map @@ -139,3 +139,9 @@ DPDK_16.07 { rte_eth_dev_get_port_by_name; rte_eth_xstats_get_names; } DPDK_16.04; + +DPDK_16.11 { + global: + + rte_eth_dev_stats_calc; +} DPDK_16.07; -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [RFC PATCH v1] rte: add bit-rate metrics to xstats 2016-08-24 14:58 [dpdk-dev] [RFC PATCH v1] rte: add bit-rate metrics to xstats Remy Horton @ 2016-08-26 13:28 ` Pattan, Reshma 2016-08-29 10:01 ` Pattan, Reshma 2016-10-28 1:04 ` [dpdk-dev] [PATCH v2 0/3] expanded statistic reporting Remy Horton 2 siblings, 0 replies; 115+ messages in thread From: Pattan, Reshma @ 2016-08-26 13:28 UTC (permalink / raw) To: Horton, Remy; +Cc: dev, thomas.monjalon Hi, > -----Original Message----- > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Remy Horton > Sent: Wednesday, August 24, 2016 3:58 PM > To: thomas.monjalon@6wind.com > Cc: dev@dpdk.org > Subject: [dpdk-dev] [RFC PATCH v1] rte: add bit-rate metrics to xstats > > This patch adds peak and average data-rate metrics to the extended statistics. > The intervals used to generate the statistics are controlled by any application > wishing to make use of these metrics. > > Signed-off-by: Remy Horton <remy.horton@intel.com> > --- > +int > +rte_eth_dev_stats_init(uint8_t port_id, uint32_t cnt_buckets) { > + struct rte_eth_dev *dev; > + struct rte_eth_dev_stats *stats; > + > + RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL); > + dev = &rte_eth_devices[port_id]; > + stats = &dev->data->stats; > + > + memset(stats, 0, sizeof(struct rte_eth_dev_stats)); > + stats->list_ibuckets = rte_zmalloc( > + NULL, sizeof(uint64_t) * cnt_buckets, 0); We can have the sizeof(uint64_t) * cnt_buckets, calculated on top and use that in both the rte_zmallocs, Instead of performing * operation twice. > + stats->list_obuckets = rte_zmalloc( > + NULL, sizeof(uint64_t) * cnt_buckets, 0); > + if (stats->list_ibuckets == NULL || stats->list_obuckets == NULL) > + return -ENOMEM; If either of them has valid pointer we should free that before returning. > + stats->cnt_buckets = cnt_buckets; > + return 0; > +} > + Thanks, Reshma ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [RFC PATCH v1] rte: add bit-rate metrics to xstats 2016-08-24 14:58 [dpdk-dev] [RFC PATCH v1] rte: add bit-rate metrics to xstats Remy Horton 2016-08-26 13:28 ` Pattan, Reshma @ 2016-08-29 10:01 ` Pattan, Reshma 2016-08-29 11:19 ` Remy Horton 2016-10-28 1:04 ` [dpdk-dev] [PATCH v2 0/3] expanded statistic reporting Remy Horton 2 siblings, 1 reply; 115+ messages in thread From: Pattan, Reshma @ 2016-08-29 10:01 UTC (permalink / raw) To: Horton, Remy, thomas.monjalon; +Cc: dev > -----Original Message----- > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Remy Horton > Sent: Wednesday, August 24, 2016 3:58 PM > To: thomas.monjalon@6wind.com > Cc: dev@dpdk.org > Subject: [dpdk-dev] [RFC PATCH v1] rte: add bit-rate metrics to xstats > > This patch adds peak and average data-rate metrics to the extended statistics. > The intervals used to generate the statistics are controlled by any application > wishing to make use of these metrics. > > Signed-off-by: Remy Horton <remy.horton@intel.com> > --- > diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c index > f62a9ec..71549b4 100644 > static const struct rte_eth_xstats_name_off rte_rxq_stats_strings[] = { > {"packets", offsetof(struct rte_eth_stats, q_ipackets)}, @@ -1499,6 > +1500,7 @@ void rte_eth_stats_reset(uint8_t port_id) { > struct rte_eth_dev *dev; > + struct rte_eth_dev_stats *dev_stats; > > RTE_ETH_VALID_PORTID_OR_RET(port_id); > dev = &rte_eth_devices[port_id]; > @@ -1506,6 +1508,19 @@ rte_eth_stats_reset(uint8_t port_id) > RTE_FUNC_PTR_OR_RET(*dev->dev_ops->stats_reset); > (*dev->dev_ops->stats_reset)(dev); > dev->data->rx_mbuf_alloc_failed = 0; > + > + /* Clear device running stat counts */ > + dev_stats = &dev->data->stats; > + memset(dev_stats->list_ibuckets, 0, > + sizeof(uint64_t) * dev_stats->cnt_buckets); > + memset(dev_stats->list_obuckets, 0, > + sizeof(uint64_t) * dev_stats->cnt_buckets); > + dev_stats->last_ibytes = 0; > + dev_stats->last_obytes = 0; > + dev_stats->peak_ibytes = 0; > + dev_stats->peak_obytes = 0; > + dev_stats->total_ibytes = 0; > + dev_stats->total_obytes = 0; > } > Should the resetting has to be done inside rte_eth_xstats_reset() instead of rte_eth_stats_reset()? Thanks, Reshma ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [RFC PATCH v1] rte: add bit-rate metrics to xstats 2016-08-29 10:01 ` Pattan, Reshma @ 2016-08-29 11:19 ` Remy Horton 0 siblings, 0 replies; 115+ messages in thread From: Remy Horton @ 2016-08-29 11:19 UTC (permalink / raw) To: Pattan, Reshma, thomas.monjalon; +Cc: dev On 29/08/2016 11:01, Pattan, Reshma wrote: [..] >> @@ -1506,6 +1508,19 @@ rte_eth_stats_reset(uint8_t port_id) [..] >> + /* Clear device running stat counts */ >> + dev_stats = &dev->data->stats; >> + memset(dev_stats->list_ibuckets, 0, >> + sizeof(uint64_t) * dev_stats->cnt_buckets); >> + memset(dev_stats->list_obuckets, 0, >> + sizeof(uint64_t) * dev_stats->cnt_buckets); >> + dev_stats->last_ibytes = 0; >> + dev_stats->last_obytes = 0; >> + dev_stats->peak_ibytes = 0; >> + dev_stats->peak_obytes = 0; >> + dev_stats->total_ibytes = 0; >> + dev_stats->total_obytes = 0; > Should the resetting has to be done inside rte_eth_xstats_reset() instead of rte_eth_stats_reset()? The bit-rate metrics are calculated from rte_eth_stats values rather than xstats values, which is why I put the reset here rather than in rte_eth_xstats_reset(). However this ought to be a moot point. I think it is a bug that rte_eth_xstats_reset() only calls rte_eth_stats_reset() if the driver doesn't implement xstats_reset, as the xstats output includes all the rte_eth_stats values unconditonally. ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v2 0/3] expanded statistic reporting 2016-08-24 14:58 [dpdk-dev] [RFC PATCH v1] rte: add bit-rate metrics to xstats Remy Horton 2016-08-26 13:28 ` Pattan, Reshma 2016-08-29 10:01 ` Pattan, Reshma @ 2016-10-28 1:04 ` Remy Horton 2016-10-28 1:04 ` [dpdk-dev] [RFC PATCH v2 1/3] lib: add information metrics library Remy Horton ` (3 more replies) 2 siblings, 4 replies; 115+ messages in thread From: Remy Horton @ 2016-10-28 1:04 UTC (permalink / raw) To: dev; +Cc: thomas.monjalon This patchset extends statistics reporting to include peak and average data-rate metrics. It comes in two parts: a statistics reporting library, and a bitrate calculation library that uses it. This structure is intended to seperate statistic reporting from ethdev and allow more flexible metric registration. -- v2 changes: * Uses a new metrics library rather than being part of ethdev Remy Horton (3): lib: add information metrics library lib: add bitrate statistics library app/test-pmd: add support for bitrate statistics app/test-pmd/testpmd.c | 30 ++- config/common_base | 10 + doc/api/doxy-api-index.md | 2 + doc/api/doxy-api.conf | 2 + lib/Makefile | 2 + lib/librte_bitratestats/Makefile | 53 ++++ lib/librte_bitratestats/rte_bitrate.c | 126 ++++++++++ lib/librte_bitratestats/rte_bitrate.h | 80 ++++++ .../rte_bitratestats_version.map | 9 + lib/librte_metrics/Makefile | 51 ++++ lib/librte_metrics/rte_metrics.c | 267 +++++++++++++++++++++ lib/librte_metrics/rte_metrics.h | 200 +++++++++++++++ lib/librte_metrics/rte_metrics_version.map | 13 + mk/rte.app.mk | 3 + 14 files changed, 847 insertions(+), 1 deletion(-) create mode 100644 lib/librte_bitratestats/Makefile create mode 100644 lib/librte_bitratestats/rte_bitrate.c create mode 100644 lib/librte_bitratestats/rte_bitrate.h create mode 100644 lib/librte_bitratestats/rte_bitratestats_version.map create mode 100644 lib/librte_metrics/Makefile create mode 100644 lib/librte_metrics/rte_metrics.c create mode 100644 lib/librte_metrics/rte_metrics.h create mode 100644 lib/librte_metrics/rte_metrics_version.map -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [RFC PATCH v2 1/3] lib: add information metrics library 2016-10-28 1:04 ` [dpdk-dev] [PATCH v2 0/3] expanded statistic reporting Remy Horton @ 2016-10-28 1:04 ` Remy Horton 2016-10-28 1:04 ` [dpdk-dev] [RFC PATCH v2 2/3] lib: add bitrate statistics library Remy Horton ` (2 subsequent siblings) 3 siblings, 0 replies; 115+ messages in thread From: Remy Horton @ 2016-10-28 1:04 UTC (permalink / raw) To: dev This patch adds a new information metric library that allows other modules to register named metrics and update their values. It is intended to be independent of ethdev, rather than mixing ethdev and non-ethdev information in xstats. Signed-off-by: Remy Horton <remy.horton@intel.com> --- config/common_base | 5 + doc/api/doxy-api-index.md | 1 + doc/api/doxy-api.conf | 1 + lib/Makefile | 1 + lib/librte_metrics/Makefile | 51 ++++++ lib/librte_metrics/rte_metrics.c | 265 +++++++++++++++++++++++++++++ lib/librte_metrics/rte_metrics.h | 200 ++++++++++++++++++++++ lib/librte_metrics/rte_metrics_version.map | 13 ++ mk/rte.app.mk | 2 + 9 files changed, 539 insertions(+) create mode 100644 lib/librte_metrics/Makefile create mode 100644 lib/librte_metrics/rte_metrics.c create mode 100644 lib/librte_metrics/rte_metrics.h create mode 100644 lib/librte_metrics/rte_metrics_version.map diff --git a/config/common_base b/config/common_base index f5d2eff..c23a632 100644 --- a/config/common_base +++ b/config/common_base @@ -592,3 +592,8 @@ CONFIG_RTE_APP_TEST_RESOURCE_TAR=n CONFIG_RTE_TEST_PMD=y CONFIG_RTE_TEST_PMD_RECORD_CORE_CYCLES=n CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n + +# +# Compile the device metrics library +# +CONFIG_RTE_LIBRTE_METRICS=y diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md index 6675f96..ca50fa6 100644 --- a/doc/api/doxy-api-index.md +++ b/doc/api/doxy-api-index.md @@ -147,4 +147,5 @@ There are many libraries, so their headers may be grouped by topics: [common] (@ref rte_common.h), [ABI compat] (@ref rte_compat.h), [keepalive] (@ref rte_keepalive.h), + [Device Metrics] (@ref rte_metrics.h), [version] (@ref rte_version.h) diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf index 9dc7ae5..fe830eb 100644 --- a/doc/api/doxy-api.conf +++ b/doc/api/doxy-api.conf @@ -57,6 +57,7 @@ INPUT = doc/api/doxy-api-index.md \ lib/librte_reorder \ lib/librte_ring \ lib/librte_sched \ + lib/librte_metrics \ lib/librte_table \ lib/librte_timer \ lib/librte_vhost diff --git a/lib/Makefile b/lib/Makefile index 990f23a..5d85dcf 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -58,6 +58,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_TABLE) += librte_table DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += librte_pipeline DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump +DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni diff --git a/lib/librte_metrics/Makefile b/lib/librte_metrics/Makefile new file mode 100644 index 0000000..8d6e23a --- /dev/null +++ b/lib/librte_metrics/Makefile @@ -0,0 +1,51 @@ +# BSD LICENSE +# +# Copyright(c) 2016 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +include $(RTE_SDK)/mk/rte.vars.mk + +# library name +LIB = librte_metrics.a + +CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) + +EXPORT_MAP := rte_metrics_version.map + +LIBABIVER := 1 + +# all source are stored in SRCS-y +SRCS-$(CONFIG_RTE_LIBRTE_METRICS) := rte_metrics.c + +# Install header file +SYMLINK-$(CONFIG_RTE_LIBRTE_METRICS)-include += rte_metrics.h + +DEPDIRS-$(CONFIG_RTE_LIBRTE_METRICS) += lib/librte_eal + +include $(RTE_SDK)/mk/rte.lib.mk diff --git a/lib/librte_metrics/rte_metrics.c b/lib/librte_metrics/rte_metrics.c new file mode 100644 index 0000000..354ba47 --- /dev/null +++ b/lib/librte_metrics/rte_metrics.c @@ -0,0 +1,265 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <string.h> +#include <sys/queue.h> + +#include <rte_common.h> +#include <rte_malloc.h> +#include <rte_metrics.h> +#include <rte_lcore.h> +#include <rte_memzone.h> + + +#define RTE_METRICS_MAX_METRICS 256 + + +/** + * Internal stats metadata and value entry. + * + * @internal + * @param name + * Name of metric + * @param value + * Current value for metric + * @param idx_next_set + * Index of next root element (zero for none) + * @param idx_next_metric + * Index of next metric in set (zero for none) + * + * Only the root of each set needs idx_next_set but since it has to be + * assumed that number of sets could equal total number of metrics, + * having a separate set metadata table doesn't save any memory. + */ +struct rte_metrics_meta_s { + struct rte_stat_name name; + uint64_t value[RTE_MAX_ETHPORTS]; + uint16_t idx_next_set; + uint16_t idx_next_stat; +}; + +/** + * Internal stats info structure. + * + * @internal + * @param idx_last_set + * Index of last metadata entry with valid data. This value is + * not valid if cnt_stats is zero. + * @param cnt_stats + * Number of metrics. + * @param metadata + * Stat data memory block. + * + * Offsets into metadata are used instead of pointers because ASLR + * means that having the same physical addresses in different + * processes is not guaranteed. + */ +struct rte_metrics_data_s { + uint16_t idx_last_set; + uint16_t cnt_stats; + struct rte_metrics_meta_s metadata[RTE_METRICS_MAX_METRICS]; +}; + + +void +rte_metrics_init(void) +{ + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + + if (rte_eal_process_type() != RTE_PROC_PRIMARY) + return; + + memzone = rte_memzone_lookup("RTE_STATS"); + if (memzone != NULL) + return; + memzone = rte_memzone_reserve("RTE_STATS", + sizeof(struct rte_metrics_data_s), rte_socket_id(), 0); + if (memzone == NULL) + rte_exit(EXIT_FAILURE, "Unable to allocate stats memzone\n"); + stats = memzone->addr; + memset(stats, 0, sizeof(struct rte_metrics_data_s)); +} + + +int +rte_metrics_reg_metric(const char *name) +{ + const char *list_names[] = {name}; + + return rte_metrics_reg_metrics(list_names, 1); +} + + +int +rte_metrics_reg_metrics(const char **names, uint16_t cnt_names) +{ + struct rte_metrics_meta_s *entry; + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + uint16_t idx_name; + uint16_t idx_base; + + /* Some sanity checks */ + if (cnt_names < 1 || names == NULL) + return -EINVAL; + + rte_metrics_init(); + memzone = rte_memzone_lookup("RTE_STATS"); + if (memzone == NULL) + return -EIO; + stats = memzone->addr; + + if (stats->cnt_stats + cnt_names >= RTE_METRICS_MAX_METRICS) + return -ENOMEM; + + /* Overwritten later if this is actually first set.. */ + stats->metadata[stats->idx_last_set].idx_next_set = stats->cnt_stats; + + stats->idx_last_set = idx_base = stats->cnt_stats; + + for (idx_name = 0; idx_name < cnt_names; idx_name++) { + entry = &stats->metadata[idx_name + stats->cnt_stats]; + strncpy(entry->name.name, names[idx_name], + RTE_METRICS_MAX_NAME_LEN); + memset(entry->value, 0, sizeof(entry->value)); + entry->idx_next_stat = idx_name + stats->cnt_stats + 1; + } + entry->idx_next_stat = 0; + entry->idx_next_set = 0; + stats->cnt_stats += cnt_names; + + return idx_base; +} + + +int +rte_metrics_update_metric(int port_id, uint16_t key, const uint64_t value) +{ + return rte_metrics_update_metrics(port_id, key, &value, 1); +} + + +int +rte_metrics_update_metrics(int port_id, + uint16_t key, + const uint64_t *values, + uint32_t count) +{ + struct rte_metrics_meta_s *entry; + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + uint16_t idx_metric; + uint16_t idx_value; + uint16_t cnt_setsize; + + rte_metrics_init(); + memzone = rte_memzone_lookup("RTE_STATS"); + if (memzone == NULL) + return -EIO; + stats = memzone->addr; + + idx_metric = key; + cnt_setsize = 1; + while (idx_metric < stats->cnt_stats) { + entry = &stats->metadata[idx_metric]; + if (entry->idx_next_stat == 0) + break; + cnt_setsize++; + idx_metric++; + } + /* Check update does not cross set border */ + if (count > cnt_setsize) + return -ERANGE; + + for (idx_value = 0; idx_value < count; idx_value++) { + idx_metric = key + idx_value; + stats->metadata[idx_metric].value[port_id] = values[idx_value]; + } + return 0; +} + + +int +rte_metrics_get_names(struct rte_stat_name *names, + uint16_t capacity) +{ + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + uint16_t idx_name; + + memzone = rte_memzone_lookup("RTE_STATS"); + /* If not allocated, fail silently */ + if (memzone == NULL) + return 0; + stats = memzone->addr; + + if (names != NULL) { + if (capacity < stats->cnt_stats) + return -ERANGE; + for (idx_name = 0; idx_name < stats->cnt_stats; idx_name++) + strncpy(names[idx_name].name, + stats->metadata[idx_name].name.name, + RTE_METRICS_MAX_NAME_LEN); + } + return stats->cnt_stats; +} + + +int +rte_metrics_get_values(int port_id, + struct rte_stat_value *values, + uint16_t capacity) +{ + struct rte_metrics_meta_s *entry; + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + uint16_t idx_name; + + memzone = rte_memzone_lookup("RTE_STATS"); + /* If not allocated, fail silently */ + if (memzone == NULL) + return 0; + stats = memzone->addr; + + if (values != NULL) { + if (capacity < stats->cnt_stats) + return -ERANGE; + for (idx_name = 0; idx_name < stats->cnt_stats; idx_name++) { + entry = &stats->metadata[idx_name]; + values[idx_name].key = idx_name; + values[idx_name].value = entry->value[port_id]; + } + } + return stats->cnt_stats; +} diff --git a/lib/librte_metrics/rte_metrics.h b/lib/librte_metrics/rte_metrics.h new file mode 100644 index 0000000..e8888eb --- /dev/null +++ b/lib/librte_metrics/rte_metrics.h @@ -0,0 +1,200 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * + * RTE Statistics module + * + * Statistic information is populated using callbacks, each of which + * is associated with one or more metric names. When queried, the + * callback is used to update all metric in the set at once. Currently + * only bulk querying of all metric is supported. + * + */ + +#ifndef _RTE_METRICS_H_ +#define _RTE_METRICS_H_ + +/** Maximum length of statistic name (including null-terminator) */ +#define RTE_METRICS_MAX_NAME_LEN 64 + +/** + * Statistic name + */ +struct rte_stat_name { + /** String describing statistic */ + char name[RTE_METRICS_MAX_NAME_LEN]; +}; + + +/** + * Statistic name. + */ +struct rte_stat_value { + /** Numeric identifier of statistic */ + uint16_t key; + /** Value for statistic */ + uint64_t value; +}; + + +/** + * Initialises statistic module. This only has to be explicitly called if you + * intend to use rte_metrics_reg_metric() or rte_metrics_reg_metrics() from a + * secondary process. + */ +void rte_metrics_init(void); + + +/** + * Register a statistic and its associated callback. + * + * @param name + * Statistic name + * + * @param callback + * Callback to use when fetching statistic + * + * @param data + * Data pointer to pass to callback + * + * @return + * - Zero or positive: Success + * - Negative: Failure + */ +int rte_metrics_reg_metric(const char *name); + +/** + * Register a set of statistic and their associated callback. + * + * @param names + * List of statistic names + * + * @param cnt_names + * Number of statistics in set + * + * @param callback + * Callback to use when fetching statsitics + * + * @param data + * Data pointer to pass to callback + * + * @return + * - Zero or positive: Success + * - Negative: Failure + */ +int rte_metrics_reg_metrics(const char **names, uint16_t cnt_names); + +/** + * Get statistic name-key lookup table. + * + * @param names + * Array of names to receive key names + * + * @param capacity + * Space available in names + * + * @return + * - Non-negative: Success (number of names) + * - Negative: Failure + */ +int rte_metrics_get_names( + struct rte_stat_name *names, + uint16_t capacity); + +/** + * Fetch statistics. + * + * @param port_id + * Port id to query + * + * @param values + * Array to receive values and their keys + * + * @param capacity + * Space available in values + * + * @return + * - Non-negative: Success (number of names) + * - Negative: Failure + */ +int rte_metrics_get_values( + int port_id, + struct rte_stat_value *values, + uint16_t capacity); + +/** + * Updates a statistic metric + * + * @param port_id + * Port to update statistics for + * @param key + * Id of statistic metric to update + * @param value + * New value + * + * @return + * - -EIO if unable to access shared statistics memory + * - Zero on success + */ +int rte_metrics_update_metric( + int port_id, + uint16_t key, + const uint64_t value); + +/** + * Updates a statistic metric set. Note that it is an error to try to + * update across a set boundary. + * + * @param port_id + * Port to update statistics for + * @param key + * Base id of statistics set to update + * @param values + * Set of new values + * @param count + * Number of new values + * + * @return + * - -ERANGE if count exceeds statistic set size + * - -EIO if upable to access shared statistics memory + * - Zero on success + */ +int rte_metrics_update_metrics( + int port_id, + uint16_t key, + const uint64_t *values, + uint32_t count); + +#endif diff --git a/lib/librte_metrics/rte_metrics_version.map b/lib/librte_metrics/rte_metrics_version.map new file mode 100644 index 0000000..a31a80a --- /dev/null +++ b/lib/librte_metrics/rte_metrics_version.map @@ -0,0 +1,13 @@ +DPDK_16.11 { + global: + + rte_metrics_get_names; + rte_metrics_get_values; + rte_metrics_init; + rte_metrics_reg_metric; + rte_metrics_reg_metrics; + rte_metrics_update_metric; + rte_metrics_update_metrics; + + local: *; +}; diff --git a/mk/rte.app.mk b/mk/rte.app.mk index ac50a21..11d0c80 100644 --- a/mk/rte.app.mk +++ b/mk/rte.app.mk @@ -97,6 +97,8 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_RING) += -lrte_ring _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL) += -lrte_eal _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE) += -lrte_cmdline _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE) += -lrte_cfgfile +_LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS) += -lrte_metrics + _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += -lrte_pmd_bond _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += -lrte_pmd_xenvirt -lxenstore -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [RFC PATCH v2 2/3] lib: add bitrate statistics library 2016-10-28 1:04 ` [dpdk-dev] [PATCH v2 0/3] expanded statistic reporting Remy Horton 2016-10-28 1:04 ` [dpdk-dev] [RFC PATCH v2 1/3] lib: add information metrics library Remy Horton @ 2016-10-28 1:04 ` Remy Horton 2016-10-28 1:12 ` Stephen Hemminger 2016-10-28 7:39 ` Morten Brørup 2016-10-28 1:04 ` [dpdk-dev] [RFC PATCH v2 3/3] app/test-pmd: add support for bitrate statistics Remy Horton 2016-11-04 3:36 ` [dpdk-dev] [PATCH v3 0/3] Expanded statistics reporting Remy Horton 3 siblings, 2 replies; 115+ messages in thread From: Remy Horton @ 2016-10-28 1:04 UTC (permalink / raw) To: dev This patch adds a library that calculates peak and average data-rate statistics. For ethernet devices. These statistics are reported using the metrics library. Signed-off-by: Remy Horton <remy.horton@intel.com> --- config/common_base | 5 + doc/api/doxy-api-index.md | 1 + doc/api/doxy-api.conf | 1 + lib/Makefile | 1 + lib/librte_bitratestats/Makefile | 53 +++++++++ lib/librte_bitratestats/rte_bitrate.c | 126 +++++++++++++++++++++ lib/librte_bitratestats/rte_bitrate.h | 80 +++++++++++++ .../rte_bitratestats_version.map | 9 ++ lib/librte_metrics/rte_metrics.c | 22 ++-- lib/librte_metrics/rte_metrics.h | 4 +- mk/rte.app.mk | 1 + 11 files changed, 291 insertions(+), 12 deletions(-) create mode 100644 lib/librte_bitratestats/Makefile create mode 100644 lib/librte_bitratestats/rte_bitrate.c create mode 100644 lib/librte_bitratestats/rte_bitrate.h create mode 100644 lib/librte_bitratestats/rte_bitratestats_version.map diff --git a/config/common_base b/config/common_base index c23a632..e778c00 100644 --- a/config/common_base +++ b/config/common_base @@ -597,3 +597,8 @@ CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n # Compile the device metrics library # CONFIG_RTE_LIBRTE_METRICS=y + +# +# Compile the bitrate statistics library +# +CONFIG_RTE_LIBRTE_BITRATE=y diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md index ca50fa6..91e8ea6 100644 --- a/doc/api/doxy-api-index.md +++ b/doc/api/doxy-api-index.md @@ -148,4 +148,5 @@ There are many libraries, so their headers may be grouped by topics: [ABI compat] (@ref rte_compat.h), [keepalive] (@ref rte_keepalive.h), [Device Metrics] (@ref rte_metrics.h), + [Bitrate Statistics] (@ref rte_bitrate.h), [version] (@ref rte_version.h) diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf index fe830eb..8765ddd 100644 --- a/doc/api/doxy-api.conf +++ b/doc/api/doxy-api.conf @@ -58,6 +58,7 @@ INPUT = doc/api/doxy-api-index.md \ lib/librte_ring \ lib/librte_sched \ lib/librte_metrics \ + lib/librte_bitratestats \ lib/librte_table \ lib/librte_timer \ lib/librte_vhost diff --git a/lib/Makefile b/lib/Makefile index 5d85dcf..e211bc0 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -59,6 +59,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += librte_pipeline DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics +DIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += librte_bitratestats ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni diff --git a/lib/librte_bitratestats/Makefile b/lib/librte_bitratestats/Makefile new file mode 100644 index 0000000..b725d4e --- /dev/null +++ b/lib/librte_bitratestats/Makefile @@ -0,0 +1,53 @@ +# BSD LICENSE +# +# Copyright(c) 2016 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +include $(RTE_SDK)/mk/rte.vars.mk + +# library name +LIB = librte_bitratestats.a + +CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) + +EXPORT_MAP := rte_bitratestats_version.map + +LIBABIVER := 1 + +# all source are stored in SRCS-y +SRCS-$(CONFIG_RTE_LIBRTE_BITRATE) := rte_bitrate.c + +# Install header file +SYMLINK-$(CONFIG_RTE_LIBRTE_BITRATE)-include += rte_bitrate.h + +DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_eal +DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_ether +DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_metrics + +include $(RTE_SDK)/mk/rte.lib.mk diff --git a/lib/librte_bitratestats/rte_bitrate.c b/lib/librte_bitratestats/rte_bitrate.c new file mode 100644 index 0000000..fcdf401 --- /dev/null +++ b/lib/librte_bitratestats/rte_bitrate.c @@ -0,0 +1,126 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <rte_common.h> +#include <rte_ethdev.h> +#include <rte_malloc.h> +#include <rte_metrics.h> +#include <rte_bitrate.h> + + +struct rte_stats_bitrate_s { + uint64_t last_ibytes; + uint64_t last_obytes; + uint64_t peak_ibits; + uint64_t peak_obits; + uint64_t ewma_ibits; + uint64_t ewma_obits; +}; + +struct rte_stats_bitrates_s { + struct rte_stats_bitrate_s port_stats[RTE_MAX_ETHPORTS]; + uint16_t id_stats_set; +}; + + +struct rte_stats_bitrates_s *rte_stats_bitrate_create(void) +{ + return rte_zmalloc(NULL, sizeof(struct rte_stats_bitrates_s), 0); +} + + +int +rte_stats_bitrate_reg(struct rte_stats_bitrates_s *bitrate_data) +{ + const char *names[] = { + "mean_bits_in", "mean_bits_out", + "peak_bits_in", "peak_bits_out", + }; + int return_value; + + bitrate_data = rte_stats_bitrate_create(); + if (bitrate_data == NULL) + rte_exit(EXIT_FAILURE, "Could not allocate bitrate data.\n"); + return_value = rte_metrics_reg_metrics(&names[0], 4); + if (return_value >= 0) + bitrate_data->id_stats_set = return_value; + return return_value; +} + + +int +rte_stats_bitrate_calc(struct rte_stats_bitrates_s *bitrate_data, + uint8_t port_id) +{ + struct rte_stats_bitrate_s *port_data; + struct rte_eth_stats eth_stats; + int ret_code; + uint64_t cnt_bits; + int64_t delta; + const int64_t alpha_percent = 20; + uint64_t values[4]; + + ret_code = rte_eth_stats_get(port_id, ð_stats); + if (ret_code != 0) + return ret_code; + + port_data = &bitrate_data->port_stats[port_id]; + + /* Incoming */ + cnt_bits = (eth_stats.ibytes - port_data->last_ibytes) << 3; + port_data->last_ibytes = eth_stats.ibytes; + if (cnt_bits > port_data->peak_ibits) + port_data->peak_ibits = cnt_bits; + delta = cnt_bits; + delta -= port_data->ewma_ibits; + delta = (delta * alpha_percent) / 100; + port_data->ewma_ibits += delta; + + /* Outgoing */ + cnt_bits = (eth_stats.obytes - port_data->last_obytes) << 3; + port_data->last_obytes = eth_stats.obytes; + if (cnt_bits > port_data->peak_obits) + port_data->peak_obits = cnt_bits; + delta = cnt_bits; + delta -= port_data->ewma_obits; + delta = (delta * alpha_percent) / 100; + port_data->ewma_obits += delta; + + values[0] = port_data->ewma_ibits; + values[1] = port_data->ewma_obits; + values[2] = port_data->peak_ibits; + values[3] = port_data->peak_obits; + rte_metrics_update_metrics(port_id, bitrate_data->id_stats_set, + values, 4); + return 0; +} diff --git a/lib/librte_bitratestats/rte_bitrate.h b/lib/librte_bitratestats/rte_bitrate.h new file mode 100644 index 0000000..cd566d6 --- /dev/null +++ b/lib/librte_bitratestats/rte_bitrate.h @@ -0,0 +1,80 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + + +/** + * Bitrate statistics data structure + */ +struct rte_stats_bitrates_s; + + +/** + * Allocate a bitrate statistics structure + * + * @return + * - Pointer to structure on success + * - NULL on error (zmalloc failure) + */ +struct rte_stats_bitrates_s *rte_stats_bitrate_create(void); + + +/** + * Register bitrate statistics + * + * @param bitrate_data + * Pointer allocated by rte_stats_create() + * + * @return + * Zero on success + * Negative on error + */ +int rte_stats_bitrate_reg(struct rte_stats_bitrates_s *bitrate_data); + + +/** + * Calculate statistics for current time window. The period this function + * is called should be the intended time window width. + * + * @param bitrate_data + * Bitrate statistics data pointer + * + * @param port_id + * Port id to calculate statistics for + * + * @return + * - Zero on success + * - Negative value on error + */ +int rte_stats_bitrate_calc(struct rte_stats_bitrates_s *bitrate_data, + uint8_t port_id); diff --git a/lib/librte_bitratestats/rte_bitratestats_version.map b/lib/librte_bitratestats/rte_bitratestats_version.map new file mode 100644 index 0000000..9de6be9 --- /dev/null +++ b/lib/librte_bitratestats/rte_bitratestats_version.map @@ -0,0 +1,9 @@ +DPDK_16.11 { + global: + + rte_stats_bitrate_calc; + rte_stats_bitrate_create; + rte_stats_bitrate_reg; + + local: *; +}; diff --git a/lib/librte_metrics/rte_metrics.c b/lib/librte_metrics/rte_metrics.c index 354ba47..7dce738 100644 --- a/lib/librte_metrics/rte_metrics.c +++ b/lib/librte_metrics/rte_metrics.c @@ -44,6 +44,8 @@ #define RTE_METRICS_MAX_METRICS 256 +#define RTE_METRICS_MEMZONE_NAME "RTE_METRICS" + /** * Internal stats metadata and value entry. * @@ -62,7 +64,7 @@ * having a separate set metadata table doesn't save any memory. */ struct rte_metrics_meta_s { - struct rte_stat_name name; + char name[RTE_METRICS_MAX_NAME_LEN]; uint64_t value[RTE_MAX_ETHPORTS]; uint16_t idx_next_set; uint16_t idx_next_stat; @@ -100,10 +102,10 @@ rte_metrics_init(void) if (rte_eal_process_type() != RTE_PROC_PRIMARY) return; - memzone = rte_memzone_lookup("RTE_STATS"); + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); if (memzone != NULL) return; - memzone = rte_memzone_reserve("RTE_STATS", + memzone = rte_memzone_reserve(RTE_METRICS_MEMZONE_NAME, sizeof(struct rte_metrics_data_s), rte_socket_id(), 0); if (memzone == NULL) rte_exit(EXIT_FAILURE, "Unable to allocate stats memzone\n"); @@ -135,7 +137,7 @@ rte_metrics_reg_metrics(const char **names, uint16_t cnt_names) return -EINVAL; rte_metrics_init(); - memzone = rte_memzone_lookup("RTE_STATS"); + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); if (memzone == NULL) return -EIO; stats = memzone->addr; @@ -150,7 +152,7 @@ rte_metrics_reg_metrics(const char **names, uint16_t cnt_names) for (idx_name = 0; idx_name < cnt_names; idx_name++) { entry = &stats->metadata[idx_name + stats->cnt_stats]; - strncpy(entry->name.name, names[idx_name], + strncpy(entry->name, names[idx_name], RTE_METRICS_MAX_NAME_LEN); memset(entry->value, 0, sizeof(entry->value)); entry->idx_next_stat = idx_name + stats->cnt_stats + 1; @@ -184,7 +186,7 @@ rte_metrics_update_metrics(int port_id, uint16_t cnt_setsize; rte_metrics_init(); - memzone = rte_memzone_lookup("RTE_STATS"); + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); if (memzone == NULL) return -EIO; stats = memzone->addr; @@ -211,14 +213,14 @@ rte_metrics_update_metrics(int port_id, int -rte_metrics_get_names(struct rte_stat_name *names, +rte_metrics_get_names(struct rte_metric_name *names, uint16_t capacity) { struct rte_metrics_data_s *stats; const struct rte_memzone *memzone; uint16_t idx_name; - memzone = rte_memzone_lookup("RTE_STATS"); + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); /* If not allocated, fail silently */ if (memzone == NULL) return 0; @@ -229,7 +231,7 @@ rte_metrics_get_names(struct rte_stat_name *names, return -ERANGE; for (idx_name = 0; idx_name < stats->cnt_stats; idx_name++) strncpy(names[idx_name].name, - stats->metadata[idx_name].name.name, + stats->metadata[idx_name].name, RTE_METRICS_MAX_NAME_LEN); } return stats->cnt_stats; @@ -246,7 +248,7 @@ rte_metrics_get_values(int port_id, const struct rte_memzone *memzone; uint16_t idx_name; - memzone = rte_memzone_lookup("RTE_STATS"); + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); /* If not allocated, fail silently */ if (memzone == NULL) return 0; diff --git a/lib/librte_metrics/rte_metrics.h b/lib/librte_metrics/rte_metrics.h index e8888eb..348db30 100644 --- a/lib/librte_metrics/rte_metrics.h +++ b/lib/librte_metrics/rte_metrics.h @@ -52,7 +52,7 @@ /** * Statistic name */ -struct rte_stat_name { +struct rte_metric_name { /** String describing statistic */ char name[RTE_METRICS_MAX_NAME_LEN]; }; @@ -130,7 +130,7 @@ int rte_metrics_reg_metrics(const char **names, uint16_t cnt_names); * - Negative: Failure */ int rte_metrics_get_names( - struct rte_stat_name *names, + struct rte_metric_name *names, uint16_t capacity); /** diff --git a/mk/rte.app.mk b/mk/rte.app.mk index 11d0c80..c499c69 100644 --- a/mk/rte.app.mk +++ b/mk/rte.app.mk @@ -98,6 +98,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL) += -lrte_eal _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE) += -lrte_cmdline _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE) += -lrte_cfgfile _LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS) += -lrte_metrics +_LDLIBS-$(CONFIG_RTE_LIBRTE_BITRATE) += -lrte_bitratestats _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += -lrte_pmd_bond -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [RFC PATCH v2 2/3] lib: add bitrate statistics library 2016-10-28 1:04 ` [dpdk-dev] [RFC PATCH v2 2/3] lib: add bitrate statistics library Remy Horton @ 2016-10-28 1:12 ` Stephen Hemminger 2016-10-28 7:48 ` Remy Horton 2016-10-28 7:39 ` Morten Brørup 1 sibling, 1 reply; 115+ messages in thread From: Stephen Hemminger @ 2016-10-28 1:12 UTC (permalink / raw) To: Remy Horton; +Cc: dev On Fri, 28 Oct 2016 09:04:30 +0800 Remy Horton <remy.horton@intel.com> wrote: > + > +struct rte_stats_bitrate_s { > + uint64_t last_ibytes; > + uint64_t last_obytes; > + uint64_t peak_ibits; > + uint64_t peak_obits; > + uint64_t ewma_ibits; > + uint64_t ewma_obits; > +}; > + Reader/write access of 64 bit values is not safe on 32 bit platforms. I think you need to add a generation counter (see Linux kernel syncp) to handle 32 bit architecture. If done correctly, it would be a nop on 64 bit platforms. ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [RFC PATCH v2 2/3] lib: add bitrate statistics library 2016-10-28 1:12 ` Stephen Hemminger @ 2016-10-28 7:48 ` Remy Horton 0 siblings, 0 replies; 115+ messages in thread From: Remy Horton @ 2016-10-28 7:48 UTC (permalink / raw) To: Stephen Hemminger; +Cc: dev On 28/10/2016 09:12, Stephen Hemminger wrote: > On Fri, 28 Oct 2016 09:04:30 +0800 > Remy Horton <remy.horton@intel.com> wrote: > >> + >> +struct rte_stats_bitrate_s { >> + uint64_t last_ibytes; >> + uint64_t last_obytes; >> + uint64_t peak_ibits; >> + uint64_t peak_obits; >> + uint64_t ewma_ibits; >> + uint64_t ewma_obits; >> +}; >> + > > Reader/write access of 64 bit values is not safe on 32 bit platforms. > I think you need to add a generation counter (see Linux kernel syncp) > to handle 32 bit architecture. If done correctly, it would be a nop > on 64 bit platforms. I don't see a problem since this is private persistent data that is only read/written from rte_stats_bitrate_calc(), and once calculated it pushes them into the metrics library using rte_metrics_update_metrics(). The idea is that downstream consumers get the values using rte_metrics_get_values() rather than reading rte_stats_bitrate_s directly. Having said that, what you mention quite likley affects the metrics library itself.. :) ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [RFC PATCH v2 2/3] lib: add bitrate statistics library 2016-10-28 1:04 ` [dpdk-dev] [RFC PATCH v2 2/3] lib: add bitrate statistics library Remy Horton 2016-10-28 1:12 ` Stephen Hemminger @ 2016-10-28 7:39 ` Morten Brørup 2016-11-01 1:53 ` Remy Horton 1 sibling, 1 reply; 115+ messages in thread From: Morten Brørup @ 2016-10-28 7:39 UTC (permalink / raw) To: Remy Horton, dev Comments below. > -----Original Message----- > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Remy Horton > Sent: Friday, October 28, 2016 3:05 AM > To: dev@dpdk.org > Subject: [dpdk-dev] [RFC PATCH v2 2/3] lib: add bitrate statistics > library > > This patch adds a library that calculates peak and average data-rate > statistics. For ethernet devices. These statistics are reported using > the metrics library. > > Signed-off-by: Remy Horton <remy.horton@intel.com> > diff --git a/lib/librte_bitratestats/rte_bitrate.c > b/lib/librte_bitratestats/rte_bitrate.c > new file mode 100644 > index 0000000..fcdf401 > --- /dev/null > +++ b/lib/librte_bitratestats/rte_bitrate.c > @@ -0,0 +1,126 @@ > +/*- > + * BSD LICENSE > + * > + * Copyright(c) 2016 Intel Corporation. All rights reserved. > + * All rights reserved. > + * > + * Redistribution and use in source and binary forms, with or > without > + * modification, are permitted provided that the following > conditions > + * are met: > + * > + * * Redistributions of source code must retain the above > copyright > + * notice, this list of conditions and the following disclaimer. > + * * Redistributions in binary form must reproduce the above > copyright > + * notice, this list of conditions and the following disclaimer > in > + * the documentation and/or other materials provided with the > + * distribution. > + * * Neither the name of Intel Corporation nor the names of its > + * contributors may be used to endorse or promote products > derived > + * from this software without specific prior written permission. > + * > + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND > CONTRIBUTORS > + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT > + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS > FOR > + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE > COPYRIGHT > + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, > INCIDENTAL, > + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT > + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF > USE, > + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON > ANY > + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR > TORT > + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE > USE > + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH > DAMAGE. > + */ > + > +#include <rte_common.h> > +#include <rte_ethdev.h> > +#include <rte_malloc.h> > +#include <rte_metrics.h> > +#include <rte_bitrate.h> > + > + > +struct rte_stats_bitrate_s { > + uint64_t last_ibytes; > + uint64_t last_obytes; > + uint64_t peak_ibits; > + uint64_t peak_obits; > + uint64_t ewma_ibits; > + uint64_t ewma_obits; > +}; > + > +struct rte_stats_bitrates_s { > + struct rte_stats_bitrate_s port_stats[RTE_MAX_ETHPORTS]; > + uint16_t id_stats_set; > +}; > + > + > +struct rte_stats_bitrates_s *rte_stats_bitrate_create(void) { > + return rte_zmalloc(NULL, sizeof(struct rte_stats_bitrates_s), 0); > } > + > + > +int > +rte_stats_bitrate_reg(struct rte_stats_bitrates_s *bitrate_data) > +{ > + const char *names[] = { > + "mean_bits_in", "mean_bits_out", > + "peak_bits_in", "peak_bits_out", > + }; > + int return_value; > + > + bitrate_data = rte_stats_bitrate_create(); > + if (bitrate_data == NULL) > + rte_exit(EXIT_FAILURE, "Could not allocate bitrate > data.\n"); > + return_value = rte_metrics_reg_metrics(&names[0], 4); > + if (return_value >= 0) > + bitrate_data->id_stats_set = return_value; > + return return_value; > +} > + > + > +int > +rte_stats_bitrate_calc(struct rte_stats_bitrates_s *bitrate_data, > + uint8_t port_id) > +{ > + struct rte_stats_bitrate_s *port_data; > + struct rte_eth_stats eth_stats; > + int ret_code; > + uint64_t cnt_bits; > + int64_t delta; > + const int64_t alpha_percent = 20; > + uint64_t values[4]; > + > + ret_code = rte_eth_stats_get(port_id, ð_stats); > + if (ret_code != 0) > + return ret_code; > + > + port_data = &bitrate_data->port_stats[port_id]; > + > + /* Incoming */ > + cnt_bits = (eth_stats.ibytes - port_data->last_ibytes) << 3; > + port_data->last_ibytes = eth_stats.ibytes; > + if (cnt_bits > port_data->peak_ibits) > + port_data->peak_ibits = cnt_bits; > + delta = cnt_bits; > + delta -= port_data->ewma_ibits; > + delta = (delta * alpha_percent) / 100; > + port_data->ewma_ibits += delta; > + > + /* Outgoing */ > + cnt_bits = (eth_stats.obytes - port_data->last_obytes) << 3; > + port_data->last_obytes = eth_stats.obytes; > + if (cnt_bits > port_data->peak_obits) > + port_data->peak_obits = cnt_bits; > + delta = cnt_bits; > + delta -= port_data->ewma_obits; > + delta = (delta * alpha_percent) / 100; > + port_data->ewma_obits += delta; > + > + values[0] = port_data->ewma_ibits; > + values[1] = port_data->ewma_obits; > + values[2] = port_data->peak_ibits; > + values[3] = port_data->peak_obits; > + rte_metrics_update_metrics(port_id, bitrate_data->id_stats_set, > + values, 4); > + return 0; > +} When working with statistical calculations using integer arithmetic, you should round off the integer result by adding 0.5 to the result, which you do by adding half of the divisor to the dividend, like this: delta = (delta * alpha_percent + 50) / 100; The numbers in this particular case are probably very big, so not rounding off doesn't affect the result a lot; but then you should add a comment about why rounding down is acceptable. Med venlig hilsen / kind regards - Morten Brørup ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [RFC PATCH v2 2/3] lib: add bitrate statistics library 2016-10-28 7:39 ` Morten Brørup @ 2016-11-01 1:53 ` Remy Horton 0 siblings, 0 replies; 115+ messages in thread From: Remy Horton @ 2016-11-01 1:53 UTC (permalink / raw) To: dev; +Cc: Morten Brørup On 28/10/2016 15:39, Morten Brørup wrote: > Comments below. [..] > When working with statistical calculations using integer arithmetic, > you should round off the integer result by adding 0.5 to the result, > which you do by adding half of the divisor to the dividend, like > this: > > delta = (delta * alpha_percent + 50) / 100; > > The numbers in this particular case are probably very big, so not > rounding off doesn't affect the result a lot; but then you should add > a comment about why rounding down is acceptable. A minor point, but will roll it into the next patchset. ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [RFC PATCH v2 3/3] app/test-pmd: add support for bitrate statistics 2016-10-28 1:04 ` [dpdk-dev] [PATCH v2 0/3] expanded statistic reporting Remy Horton 2016-10-28 1:04 ` [dpdk-dev] [RFC PATCH v2 1/3] lib: add information metrics library Remy Horton 2016-10-28 1:04 ` [dpdk-dev] [RFC PATCH v2 2/3] lib: add bitrate statistics library Remy Horton @ 2016-10-28 1:04 ` Remy Horton 2016-11-04 3:36 ` [dpdk-dev] [PATCH v3 0/3] Expanded statistics reporting Remy Horton 3 siblings, 0 replies; 115+ messages in thread From: Remy Horton @ 2016-10-28 1:04 UTC (permalink / raw) To: dev Signed-off-by: Remy Horton <remy.horton@intel.com> --- app/test-pmd/testpmd.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c index e2403c3..940dc3b 100644 --- a/app/test-pmd/testpmd.c +++ b/app/test-pmd/testpmd.c @@ -78,6 +78,8 @@ #ifdef RTE_LIBRTE_PDUMP #include <rte_pdump.h> #endif +#include <rte_metrics.h> +#include <rte_bitrate.h> #include "testpmd.h" @@ -322,6 +324,9 @@ uint16_t nb_rx_queue_stats_mappings = 0; unsigned max_socket = 0; +/* Bitrate statistics */ +struct rte_stats_bitrates_s *bitrate_data; + /* Forward function declarations */ static void map_port_queue_stats_mapping_registers(uint8_t pi, struct rte_port *port); static void check_all_ports_link_status(uint32_t port_mask); @@ -921,12 +926,26 @@ run_pkt_fwd_on_lcore(struct fwd_lcore *fc, packet_fwd_t pkt_fwd) struct fwd_stream **fsm; streamid_t nb_fs; streamid_t sm_id; - + uint64_t tics_per_1sec; + uint64_t tics_datum; + uint64_t tics_current; + uint8_t idx_port, cnt_ports; + + cnt_ports = rte_eth_dev_count(); + tics_datum = rte_rdtsc(); + tics_per_1sec = rte_get_timer_hz(); fsm = &fwd_streams[fc->stream_idx]; nb_fs = fc->stream_nb; do { for (sm_id = 0; sm_id < nb_fs; sm_id++) (*pkt_fwd)(fsm[sm_id]); + tics_current = rte_rdtsc(); + if (tics_current - tics_datum >= tics_per_1sec) { + /* Periodic bitrate calculation */ + for (idx_port = 0; idx_port < cnt_ports; idx_port++) + rte_stats_bitrate_calc(bitrate_data, idx_port); + tics_datum = tics_current; + } } while (! fc->stopped); } @@ -2119,6 +2138,15 @@ main(int argc, char** argv) FOREACH_PORT(port_id, ports) rte_eth_promiscuous_enable(port_id); + /* Setup bitrate stats */ + bitrate_data = rte_stats_bitrate_create(); + if (bitrate_data == NULL) + rte_exit(EXIT_FAILURE, "Could not allocate bitrate data.\n"); + rte_stats_bitrate_reg(bitrate_data); + int id_const = rte_metrics_reg_metric("constant"); + rte_metrics_update_metric(55, id_const, 0xdeadbeef); + + #ifdef RTE_LIBRTE_CMDLINE if (interactive == 1) { if (auto_start) { -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v3 0/3] Expanded statistics reporting 2016-10-28 1:04 ` [dpdk-dev] [PATCH v2 0/3] expanded statistic reporting Remy Horton ` (2 preceding siblings ...) 2016-10-28 1:04 ` [dpdk-dev] [RFC PATCH v2 3/3] app/test-pmd: add support for bitrate statistics Remy Horton @ 2016-11-04 3:36 ` Remy Horton 2016-11-04 3:36 ` [dpdk-dev] [PATCH v3 1/3] lib: add information metrics library Remy Horton ` (3 more replies) 3 siblings, 4 replies; 115+ messages in thread From: Remy Horton @ 2016-11-04 3:36 UTC (permalink / raw) To: dev; +Cc: Thomas Monjalon This patchset extends statistics reporting to include peak and average data-rate metrics. It comes in two parts: a statistics reporting library, and a bitrate calculation library that uses it. This structure is intended to seperate statistic reporting from ethdev and allow more flexible metric registration. -- v3 changes: * Marked rte_stats_bitrate_s as internal * Minor integer roundoff correction * Coding style corrections * Removed spurious object allocation * Changes to rte_metrics.[ch] moved from Patch 2/3 to 1/3. * Reintroduced non-port values (RTE_METRICS_NONPORT) * Added spinlocks to metric library * Removed spurious test registration/update * Added release notes entries v2 changes: * Uses a new metrics library rather than being part of ethdev Remy Horton (3): lib: add information metrics library lib: add bitrate statistics library app/test-pmd: add support for bitrate statistics app/test-pmd/testpmd.c | 28 +- config/common_base | 10 + doc/api/doxy-api-index.md | 2 + doc/api/doxy-api.conf | 2 + doc/guides/rel_notes/release_16_11.rst | 11 + lib/Makefile | 2 + lib/librte_bitratestats/Makefile | 53 ++++ lib/librte_bitratestats/rte_bitrate.c | 128 +++++++++ lib/librte_bitratestats/rte_bitrate.h | 80 ++++++ .../rte_bitratestats_version.map | 9 + lib/librte_metrics/Makefile | 51 ++++ lib/librte_metrics/rte_metrics.c | 300 +++++++++++++++++++++ lib/librte_metrics/rte_metrics.h | 204 ++++++++++++++ lib/librte_metrics/rte_metrics_version.map | 13 + mk/rte.app.mk | 3 + 15 files changed, 895 insertions(+), 1 deletion(-) create mode 100644 lib/librte_bitratestats/Makefile create mode 100644 lib/librte_bitratestats/rte_bitrate.c create mode 100644 lib/librte_bitratestats/rte_bitrate.h create mode 100644 lib/librte_bitratestats/rte_bitratestats_version.map create mode 100644 lib/librte_metrics/Makefile create mode 100644 lib/librte_metrics/rte_metrics.c create mode 100644 lib/librte_metrics/rte_metrics.h create mode 100644 lib/librte_metrics/rte_metrics_version.map -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v3 1/3] lib: add information metrics library 2016-11-04 3:36 ` [dpdk-dev] [PATCH v3 0/3] Expanded statistics reporting Remy Horton @ 2016-11-04 3:36 ` Remy Horton 2016-11-04 16:42 ` Pattan, Reshma 2016-11-04 3:36 ` [dpdk-dev] [PATCH v3 2/3] lib: add bitrate statistics library Remy Horton ` (2 subsequent siblings) 3 siblings, 1 reply; 115+ messages in thread From: Remy Horton @ 2016-11-04 3:36 UTC (permalink / raw) To: dev This patch adds a new information metric library that allows other modules to register named metrics and update their values. It is intended to be independent of ethdev, rather than mixing ethdev and non-ethdev information in xstats. Signed-off-by: Remy Horton <remy.horton@intel.com> --- config/common_base | 5 + doc/api/doxy-api-index.md | 1 + doc/api/doxy-api.conf | 1 + doc/guides/rel_notes/release_16_11.rst | 6 + lib/Makefile | 1 + lib/librte_metrics/Makefile | 51 +++++ lib/librte_metrics/rte_metrics.c | 300 +++++++++++++++++++++++++++++ lib/librte_metrics/rte_metrics.h | 204 ++++++++++++++++++++ lib/librte_metrics/rte_metrics_version.map | 13 ++ mk/rte.app.mk | 2 + 10 files changed, 584 insertions(+) create mode 100644 lib/librte_metrics/Makefile create mode 100644 lib/librte_metrics/rte_metrics.c create mode 100644 lib/librte_metrics/rte_metrics.h create mode 100644 lib/librte_metrics/rte_metrics_version.map diff --git a/config/common_base b/config/common_base index 21d18f8..2277727 100644 --- a/config/common_base +++ b/config/common_base @@ -589,3 +589,8 @@ CONFIG_RTE_APP_TEST_RESOURCE_TAR=n CONFIG_RTE_TEST_PMD=y CONFIG_RTE_TEST_PMD_RECORD_CORE_CYCLES=n CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n + +# +# Compile the device metrics library +# +CONFIG_RTE_LIBRTE_METRICS=y diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md index 6675f96..ca50fa6 100644 --- a/doc/api/doxy-api-index.md +++ b/doc/api/doxy-api-index.md @@ -147,4 +147,5 @@ There are many libraries, so their headers may be grouped by topics: [common] (@ref rte_common.h), [ABI compat] (@ref rte_compat.h), [keepalive] (@ref rte_keepalive.h), + [Device Metrics] (@ref rte_metrics.h), [version] (@ref rte_version.h) diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf index 9dc7ae5..fe830eb 100644 --- a/doc/api/doxy-api.conf +++ b/doc/api/doxy-api.conf @@ -57,6 +57,7 @@ INPUT = doc/api/doxy-api-index.md \ lib/librte_reorder \ lib/librte_ring \ lib/librte_sched \ + lib/librte_metrics \ lib/librte_table \ lib/librte_timer \ lib/librte_vhost diff --git a/doc/guides/rel_notes/release_16_11.rst b/doc/guides/rel_notes/release_16_11.rst index aa0c09a..507f715 100644 --- a/doc/guides/rel_notes/release_16_11.rst +++ b/doc/guides/rel_notes/release_16_11.rst @@ -131,6 +131,12 @@ New Features The GCC 4.9 ``-march`` option supports the Intel processor code names. The config option ``RTE_MACHINE`` can be used to pass code names to the compiler as ``-march`` flag. +* **Added information metric library.** + + A library that allows information metrics to be added and update. It is + intended to provide a reporting mechanism that is independent of the + ethdev library. + Resolved Issues --------------- diff --git a/lib/Makefile b/lib/Makefile index 990f23a..5d85dcf 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -58,6 +58,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_TABLE) += librte_table DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += librte_pipeline DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump +DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni diff --git a/lib/librte_metrics/Makefile b/lib/librte_metrics/Makefile new file mode 100644 index 0000000..8d6e23a --- /dev/null +++ b/lib/librte_metrics/Makefile @@ -0,0 +1,51 @@ +# BSD LICENSE +# +# Copyright(c) 2016 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +include $(RTE_SDK)/mk/rte.vars.mk + +# library name +LIB = librte_metrics.a + +CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) + +EXPORT_MAP := rte_metrics_version.map + +LIBABIVER := 1 + +# all source are stored in SRCS-y +SRCS-$(CONFIG_RTE_LIBRTE_METRICS) := rte_metrics.c + +# Install header file +SYMLINK-$(CONFIG_RTE_LIBRTE_METRICS)-include += rte_metrics.h + +DEPDIRS-$(CONFIG_RTE_LIBRTE_METRICS) += lib/librte_eal + +include $(RTE_SDK)/mk/rte.lib.mk diff --git a/lib/librte_metrics/rte_metrics.c b/lib/librte_metrics/rte_metrics.c new file mode 100644 index 0000000..220c2ac --- /dev/null +++ b/lib/librte_metrics/rte_metrics.c @@ -0,0 +1,300 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <string.h> +#include <sys/queue.h> + +#include <rte_common.h> +#include <rte_malloc.h> +#include <rte_metrics.h> +#include <rte_lcore.h> +#include <rte_memzone.h> +#include <rte_spinlock.h> + +#define RTE_METRICS_MAX_METRICS 256 +#define RTE_METRICS_MEMZONE_NAME "RTE_METRICS" + +/** + * Internal stats metadata and value entry. + * + * @internal + * @param name + * Name of metric + * @param value + * Current value for metric + * @param idx_next_set + * Index of next root element (zero for none) + * @param idx_next_metric + * Index of next metric in set (zero for none) + * + * Only the root of each set needs idx_next_set but since it has to be + * assumed that number of sets could equal total number of metrics, + * having a separate set metadata table doesn't save any memory. + */ +struct rte_metrics_meta_s { + char name[RTE_METRICS_MAX_NAME_LEN]; + uint64_t value[RTE_MAX_ETHPORTS]; + uint64_t nonport_value; + uint16_t idx_next_set; + uint16_t idx_next_stat; +}; + +/** + * Internal stats info structure. + * + * @internal + * @param idx_last_set + * Index of last metadata entry with valid data. This value is + * not valid if cnt_stats is zero. + * @param cnt_stats + * Number of metrics. + * @param metadata + * Stat data memory block. + * + * Offsets into metadata are used instead of pointers because ASLR + * means that having the same physical addresses in different + * processes is not guaranteed. + */ +struct rte_metrics_data_s { + uint16_t idx_last_set; + uint16_t cnt_stats; + struct rte_metrics_meta_s metadata[RTE_METRICS_MAX_METRICS]; + rte_spinlock_t lock; +}; + + +void +rte_metrics_init(void) +{ + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + + if (rte_eal_process_type() != RTE_PROC_PRIMARY) + return; + + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); + if (memzone != NULL) + return; + memzone = rte_memzone_reserve(RTE_METRICS_MEMZONE_NAME, + sizeof(struct rte_metrics_data_s), rte_socket_id(), 0); + if (memzone == NULL) + rte_exit(EXIT_FAILURE, "Unable to allocate stats memzone\n"); + stats = memzone->addr; + memset(stats, 0, sizeof(struct rte_metrics_data_s)); + rte_spinlock_init(&stats->lock); +} + + +int +rte_metrics_reg_metric(const char *name) +{ + const char *list_names[] = {name}; + + return rte_metrics_reg_metrics(list_names, 1); +} + + +int +rte_metrics_reg_metrics(const char **names, uint16_t cnt_names) +{ + struct rte_metrics_meta_s *entry; + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + uint16_t idx_name; + uint16_t idx_base; + + /* Some sanity checks */ + if (cnt_names < 1 || names == NULL) + return -EINVAL; + + rte_metrics_init(); + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); + if (memzone == NULL) + return -EIO; + stats = memzone->addr; + + if (stats->cnt_stats + cnt_names >= RTE_METRICS_MAX_METRICS) + return -ENOMEM; + + rte_spinlock_lock(&stats->lock); + + /* Overwritten later if this is actually first set.. */ + stats->metadata[stats->idx_last_set].idx_next_set = stats->cnt_stats; + + stats->idx_last_set = idx_base = stats->cnt_stats; + + for (idx_name = 0; idx_name < cnt_names; idx_name++) { + entry = &stats->metadata[idx_name + stats->cnt_stats]; + strncpy(entry->name, names[idx_name], + RTE_METRICS_MAX_NAME_LEN); + memset(entry->value, 0, sizeof(entry->value)); + entry->idx_next_stat = idx_name + stats->cnt_stats + 1; + } + entry->idx_next_stat = 0; + entry->idx_next_set = 0; + stats->cnt_stats += cnt_names; + + rte_spinlock_unlock(&stats->lock); + + return idx_base; +} + + +int +rte_metrics_update_metric(int port_id, uint16_t key, const uint64_t value) +{ + return rte_metrics_update_metrics(port_id, key, &value, 1); +} + + +int +rte_metrics_update_metrics(int port_id, + uint16_t key, + const uint64_t *values, + uint32_t count) +{ + struct rte_metrics_meta_s *entry; + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + uint16_t idx_metric; + uint16_t idx_value; + uint16_t cnt_setsize; + + if (port_id != RTE_METRICS_NONPORT && + (port_id < 0 || port_id > RTE_MAX_ETHPORTS)) + return -EINVAL; + + rte_metrics_init(); + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); + if (memzone == NULL) + return -EIO; + stats = memzone->addr; + + rte_spinlock_lock(&stats->lock); + idx_metric = key; + cnt_setsize = 1; + while (idx_metric < stats->cnt_stats) { + entry = &stats->metadata[idx_metric]; + if (entry->idx_next_stat == 0) + break; + cnt_setsize++; + idx_metric++; + } + /* Check update does not cross set border */ + if (count > cnt_setsize) { + rte_spinlock_unlock(&stats->lock); + return -ERANGE; + } + + if (port_id == RTE_METRICS_NONPORT) + for (idx_value = 0; idx_value < count; idx_value++) { + idx_metric = key + idx_value; + stats->metadata[idx_metric].nonport_value = + values[idx_value]; + } + else + for (idx_value = 0; idx_value < count; idx_value++) { + idx_metric = key + idx_value; + stats->metadata[idx_metric].value[port_id] = + values[idx_value]; + } + rte_spinlock_unlock(&stats->lock); + return 0; +} + + +int +rte_metrics_get_names(struct rte_metric_name *names, + uint16_t capacity) +{ + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + uint16_t idx_name; + int return_value; + + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); + /* If not allocated, fail silently */ + if (memzone == NULL) + return 0; + + stats = memzone->addr; + rte_spinlock_lock(&stats->lock); + if (names != NULL) { + if (capacity < stats->cnt_stats) { + rte_spinlock_unlock(&stats->lock); + return -ERANGE; + } + for (idx_name = 0; idx_name < stats->cnt_stats; idx_name++) + strncpy(names[idx_name].name, + stats->metadata[idx_name].name, + RTE_METRICS_MAX_NAME_LEN); + } + return_value = stats->cnt_stats; + rte_spinlock_unlock(&stats->lock); + return return_value; +} + + +int +rte_metrics_get_values(int port_id, + struct rte_stat_value *values, + uint16_t capacity) +{ + struct rte_metrics_meta_s *entry; + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + uint16_t idx_name; + int return_value; + + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); + /* If not allocated, fail silently */ + if (memzone == NULL) + return 0; + stats = memzone->addr; + rte_spinlock_lock(&stats->lock); + + if (values != NULL) { + if (capacity < stats->cnt_stats) { + rte_spinlock_unlock(&stats->lock); + return -ERANGE; + } + for (idx_name = 0; idx_name < stats->cnt_stats; idx_name++) { + entry = &stats->metadata[idx_name]; + values[idx_name].key = idx_name; + values[idx_name].value = entry->value[port_id]; + } + } + return_value = stats->cnt_stats; + rte_spinlock_unlock(&stats->lock); + return return_value; +} diff --git a/lib/librte_metrics/rte_metrics.h b/lib/librte_metrics/rte_metrics.h new file mode 100644 index 0000000..6b75404 --- /dev/null +++ b/lib/librte_metrics/rte_metrics.h @@ -0,0 +1,204 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * + * RTE Statistics module + * + * Statistic information is populated using callbacks, each of which + * is associated with one or more metric names. When queried, the + * callback is used to update all metric in the set at once. Currently + * only bulk querying of all metric is supported. + * + */ + +#ifndef _RTE_METRICS_H_ +#define _RTE_METRICS_H_ + +/** Maximum length of statistic name (including null-terminator) */ +#define RTE_METRICS_MAX_NAME_LEN 64 + +/** Used to indicate port-independent information */ +#define RTE_METRICS_NONPORT -1 + + +/** + * Statistic name + */ +struct rte_metric_name { + /** String describing statistic */ + char name[RTE_METRICS_MAX_NAME_LEN]; +}; + + +/** + * Statistic name. + */ +struct rte_stat_value { + /** Numeric identifier of statistic */ + uint16_t key; + /** Value for statistic */ + uint64_t value; +}; + + +/** + * Initialises statistic module. This only has to be explicitly called if you + * intend to use rte_metrics_reg_metric() or rte_metrics_reg_metrics() from a + * secondary process. + */ +void rte_metrics_init(void); + + +/** + * Register a statistic and its associated callback. + * + * @param name + * Statistic name + * + * @param callback + * Callback to use when fetching statistic + * + * @param data + * Data pointer to pass to callback + * + * @return + * - Zero or positive: Success + * - Negative: Failure + */ +int rte_metrics_reg_metric(const char *name); + +/** + * Register a set of statistic and their associated callback. + * + * @param names + * List of statistic names + * + * @param cnt_names + * Number of statistics in set + * + * @param callback + * Callback to use when fetching statsitics + * + * @param data + * Data pointer to pass to callback + * + * @return + * - Zero or positive: Success + * - Negative: Failure + */ +int rte_metrics_reg_metrics(const char **names, uint16_t cnt_names); + +/** + * Get statistic name-key lookup table. + * + * @param names + * Array of names to receive key names + * + * @param capacity + * Space available in names + * + * @return + * - Non-negative: Success (number of names) + * - Negative: Failure + */ +int rte_metrics_get_names( + struct rte_metric_name *names, + uint16_t capacity); + +/** + * Fetch statistics. + * + * @param port_id + * Port id to query + * + * @param values + * Array to receive values and their keys + * + * @param capacity + * Space available in values + * + * @return + * - Non-negative: Success (number of names) + * - Negative: Failure + */ +int rte_metrics_get_values( + int port_id, + struct rte_stat_value *values, + uint16_t capacity); + +/** + * Updates a statistic metric + * + * @param port_id + * Port to update statistics for + * @param key + * Id of statistic metric to update + * @param value + * New value + * + * @return + * - -EIO if unable to access shared statistics memory + * - Zero on success + */ +int rte_metrics_update_metric( + int port_id, + uint16_t key, + const uint64_t value); + +/** + * Updates a statistic metric set. Note that it is an error to try to + * update across a set boundary. + * + * @param port_id + * Port to update statistics for + * @param key + * Base id of statistics set to update + * @param values + * Set of new values + * @param count + * Number of new values + * + * @return + * - -ERANGE if count exceeds statistic set size + * - -EIO if upable to access shared statistics memory + * - Zero on success + */ +int rte_metrics_update_metrics( + int port_id, + uint16_t key, + const uint64_t *values, + uint32_t count); + +#endif diff --git a/lib/librte_metrics/rte_metrics_version.map b/lib/librte_metrics/rte_metrics_version.map new file mode 100644 index 0000000..a31a80a --- /dev/null +++ b/lib/librte_metrics/rte_metrics_version.map @@ -0,0 +1,13 @@ +DPDK_16.11 { + global: + + rte_metrics_get_names; + rte_metrics_get_values; + rte_metrics_init; + rte_metrics_reg_metric; + rte_metrics_reg_metrics; + rte_metrics_update_metric; + rte_metrics_update_metrics; + + local: *; +}; diff --git a/mk/rte.app.mk b/mk/rte.app.mk index 51bc3b0..2db5427 100644 --- a/mk/rte.app.mk +++ b/mk/rte.app.mk @@ -98,6 +98,8 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_RING) += -lrte_ring _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL) += -lrte_eal _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE) += -lrte_cmdline _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE) += -lrte_cfgfile +_LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS) += -lrte_metrics + _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += -lrte_pmd_bond _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += -lrte_pmd_xenvirt -lxenstore -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [PATCH v3 1/3] lib: add information metrics library 2016-11-04 3:36 ` [dpdk-dev] [PATCH v3 1/3] lib: add information metrics library Remy Horton @ 2016-11-04 16:42 ` Pattan, Reshma 2016-11-07 15:25 ` Pattan, Reshma 0 siblings, 1 reply; 115+ messages in thread From: Pattan, Reshma @ 2016-11-04 16:42 UTC (permalink / raw) To: Horton, Remy; +Cc: dev Hi, Few comments below. > -----Original Message----- > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Remy Horton > Sent: Friday, November 4, 2016 3:36 AM > To: dev@dpdk.org > Subject: [dpdk-dev] [PATCH v3 1/3] lib: add information metrics library > > This patch adds a new information metric library that allows other modules > to register named metrics and update their values. It is intended to be > independent of ethdev, rather than mixing ethdev and non-ethdev > information in xstats. > > Signed-off-by: Remy Horton <remy.horton@intel.com> > --- > +int > + > +int > +rte_metrics_get_values(int port_id, > + struct rte_stat_value *values, > + uint16_t capacity) > +{ > + struct rte_metrics_meta_s *entry; > + struct rte_metrics_data_s *stats; > + const struct rte_memzone *memzone; > + uint16_t idx_name; > + int return_value; > + > + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); > + /* If not allocated, fail silently */ > + if (memzone == NULL) > + return 0; > + stats = memzone->addr; > + rte_spinlock_lock(&stats->lock); > + > + if (values != NULL) { > + if (capacity < stats->cnt_stats) { > + rte_spinlock_unlock(&stats->lock); > + return -ERANGE; > + } > + for (idx_name = 0; idx_name < stats->cnt_stats; idx_name++) > { > + entry = &stats->metadata[idx_name]; > + values[idx_name].key = idx_name; > + values[idx_name].value = entry->value[port_id]; > + } Here you also need to include logic to return values for port independent metrics. > diff --git a/lib/librte_metrics/rte_metrics.h b/lib/librte_metrics/rte_metrics.h > new file mode 100644 > index 0000000..6b75404 > --- /dev/null > +++ b/lib/librte_metrics/rte_metrics.h > @@ -0,0 +1,204 @@ > +/** > + * Statistic name > + */ > +struct rte_metric_name { > + /** String describing statistic */ > + char name[RTE_METRICS_MAX_NAME_LEN]; > +}; > + > + > +/** > + * Statistic name. > + */ Need to correct the description to "stats values" or "metric values." > +struct rte_stat_value { Need to change the name to rte_metric_value. > + /** Numeric identifier of statistic */ > + uint16_t key; > + /** Value for statistic */ > + uint64_t value; > +}; > + > + > +/** > + * Initialises statistic module. This only has to be explicitly called Typo < Initialises> Thanks, Reshma ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [PATCH v3 1/3] lib: add information metrics library 2016-11-04 16:42 ` Pattan, Reshma @ 2016-11-07 15:25 ` Pattan, Reshma 2016-11-08 3:19 ` Remy Horton 0 siblings, 1 reply; 115+ messages in thread From: Pattan, Reshma @ 2016-11-07 15:25 UTC (permalink / raw) To: Horton, Remy; +Cc: 'dev@dpdk.org' Hi, > -----Original Message----- > From: Pattan, Reshma > Sent: Friday, November 4, 2016 4:43 PM > To: Remy Horton <remy.horton@intel.com> > Cc: dev@dpdk.org > Subject: RE: [dpdk-dev] [PATCH v3 1/3] lib: add information metrics library > > Hi, > > Few comments below. > > > -----Original Message----- > > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Remy Horton > > Sent: Friday, November 4, 2016 3:36 AM > > To: dev@dpdk.org > > Subject: [dpdk-dev] [PATCH v3 1/3] lib: add information metrics > > library > > > > This patch adds a new information metric library that allows other > > modules to register named metrics and update their values. It is > > intended to be independent of ethdev, rather than mixing ethdev and > > non-ethdev information in xstats. > > > > Signed-off-by: Remy Horton <remy.horton@intel.com> > > --- > > +int > > + > > +int > > +rte_metrics_get_values(int port_id, > > + struct rte_stat_value *values, > > + uint16_t capacity) > > +{ > > + struct rte_metrics_meta_s *entry; > > + struct rte_metrics_data_s *stats; > > + const struct rte_memzone *memzone; > > + uint16_t idx_name; > > + int return_value; > > + > > + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); > > + /* If not allocated, fail silently */ > > + if (memzone == NULL) > > + return 0; > > + stats = memzone->addr; > > + rte_spinlock_lock(&stats->lock); > > + > > + if (values != NULL) { > > + if (capacity < stats->cnt_stats) { > > + rte_spinlock_unlock(&stats->lock); > > + return -ERANGE; > > + } > > + for (idx_name = 0; idx_name < stats->cnt_stats; idx_name++) > > { > > + entry = &stats->metadata[idx_name]; > > + values[idx_name].key = idx_name; > > + values[idx_name].value = entry->value[port_id]; > > + } > > Here you also need to include logic to return values for port independent > metrics. > > > diff --git a/lib/librte_metrics/rte_metrics.h > > b/lib/librte_metrics/rte_metrics.h > > new file mode 100644 > > index 0000000..6b75404 > > --- /dev/null > > +++ b/lib/librte_metrics/rte_metrics.h > > @@ -0,0 +1,204 @@ > > +/** > > + * Statistic name > > + */ > > +struct rte_metric_name { > > + /** String describing statistic */ > > + char name[RTE_METRICS_MAX_NAME_LEN]; }; > > + > > + > > +/** > > + * Statistic name. > > + */ > > Need to correct the description to "stats values" or "metric values." > > > +struct rte_stat_value { > > Need to change the name to rte_metric_value. > > > + /** Numeric identifier of statistic */ > > + uint16_t key; > > + /** Value for statistic */ > > + uint64_t value; > > +}; > > + > > + > > +/** > > + * Initialises statistic module. This only has to be explicitly > > +called > > Typo < Initialises> To avoid confusion, here I mean to say "Initializes" should be used (i.e. US English) . Also another non-related comment, you may need to add a comment about EMWA near the mean bit rate calculation code. > > Thanks, > Reshma ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [PATCH v3 1/3] lib: add information metrics library 2016-11-07 15:25 ` Pattan, Reshma @ 2016-11-08 3:19 ` Remy Horton 0 siblings, 0 replies; 115+ messages in thread From: Remy Horton @ 2016-11-08 3:19 UTC (permalink / raw) To: Pattan, Reshma; +Cc: dev On 07/11/2016 23:25, Pattan, Reshma wrote: [..] >>> + * Initialises statistic module. This only has to be explicitly >>> +called >> >> Typo < Initialises> > > To avoid confusion, here I mean to say "Initializes" should be used (i.e. US English) . Sorta guessed that.. :) > Also another non-related comment, you may need to add a comment about EMWA > near the mean bit rate calculation code. Quite a few comments needed updating. Going to hold off the v5 until 16.11 is out as I'll also need to change all the references to 17.02.. ..Remy ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v3 2/3] lib: add bitrate statistics library 2016-11-04 3:36 ` [dpdk-dev] [PATCH v3 0/3] Expanded statistics reporting Remy Horton 2016-11-04 3:36 ` [dpdk-dev] [PATCH v3 1/3] lib: add information metrics library Remy Horton @ 2016-11-04 3:36 ` Remy Horton 2016-11-04 3:36 ` [dpdk-dev] [PATCH v3 3/3] app/test-pmd: add support for bitrate statistics Remy Horton 2016-11-15 7:15 ` [dpdk-dev] [PATCH v4 0/3] Expanded statistics reporting Remy Horton 3 siblings, 0 replies; 115+ messages in thread From: Remy Horton @ 2016-11-04 3:36 UTC (permalink / raw) To: dev This patch adds a library that calculates peak and average data-rate statistics. For ethernet devices. These statistics are reported using the metrics library. Signed-off-by: Remy Horton <remy.horton@intel.com> --- config/common_base | 5 + doc/api/doxy-api-index.md | 1 + doc/api/doxy-api.conf | 1 + doc/guides/rel_notes/release_16_11.rst | 5 + lib/Makefile | 1 + lib/librte_bitratestats/Makefile | 53 +++++++++ lib/librte_bitratestats/rte_bitrate.c | 128 +++++++++++++++++++++ lib/librte_bitratestats/rte_bitrate.h | 80 +++++++++++++ .../rte_bitratestats_version.map | 9 ++ mk/rte.app.mk | 1 + 10 files changed, 284 insertions(+) create mode 100644 lib/librte_bitratestats/Makefile create mode 100644 lib/librte_bitratestats/rte_bitrate.c create mode 100644 lib/librte_bitratestats/rte_bitrate.h create mode 100644 lib/librte_bitratestats/rte_bitratestats_version.map diff --git a/config/common_base b/config/common_base index 2277727..25c3911 100644 --- a/config/common_base +++ b/config/common_base @@ -594,3 +594,8 @@ CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n # Compile the device metrics library # CONFIG_RTE_LIBRTE_METRICS=y + +# +# Compile the bitrate statistics library +# +CONFIG_RTE_LIBRTE_BITRATE=y diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md index ca50fa6..91e8ea6 100644 --- a/doc/api/doxy-api-index.md +++ b/doc/api/doxy-api-index.md @@ -148,4 +148,5 @@ There are many libraries, so their headers may be grouped by topics: [ABI compat] (@ref rte_compat.h), [keepalive] (@ref rte_keepalive.h), [Device Metrics] (@ref rte_metrics.h), + [Bitrate Statistics] (@ref rte_bitrate.h), [version] (@ref rte_version.h) diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf index fe830eb..8765ddd 100644 --- a/doc/api/doxy-api.conf +++ b/doc/api/doxy-api.conf @@ -58,6 +58,7 @@ INPUT = doc/api/doxy-api-index.md \ lib/librte_ring \ lib/librte_sched \ lib/librte_metrics \ + lib/librte_bitratestats \ lib/librte_table \ lib/librte_timer \ lib/librte_vhost diff --git a/doc/guides/rel_notes/release_16_11.rst b/doc/guides/rel_notes/release_16_11.rst index 507f715..b690b72 100644 --- a/doc/guides/rel_notes/release_16_11.rst +++ b/doc/guides/rel_notes/release_16_11.rst @@ -137,6 +137,11 @@ New Features intended to provide a reporting mechanism that is independent of the ethdev library. +* **Added bit-rate calculation library.** + + A library that can be used to calculate device bit-rates. Calculated + bitrates are reported using the metrics library. + Resolved Issues --------------- diff --git a/lib/Makefile b/lib/Makefile index 5d85dcf..e211bc0 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -59,6 +59,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += librte_pipeline DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics +DIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += librte_bitratestats ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni diff --git a/lib/librte_bitratestats/Makefile b/lib/librte_bitratestats/Makefile new file mode 100644 index 0000000..b725d4e --- /dev/null +++ b/lib/librte_bitratestats/Makefile @@ -0,0 +1,53 @@ +# BSD LICENSE +# +# Copyright(c) 2016 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +include $(RTE_SDK)/mk/rte.vars.mk + +# library name +LIB = librte_bitratestats.a + +CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) + +EXPORT_MAP := rte_bitratestats_version.map + +LIBABIVER := 1 + +# all source are stored in SRCS-y +SRCS-$(CONFIG_RTE_LIBRTE_BITRATE) := rte_bitrate.c + +# Install header file +SYMLINK-$(CONFIG_RTE_LIBRTE_BITRATE)-include += rte_bitrate.h + +DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_eal +DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_ether +DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_metrics + +include $(RTE_SDK)/mk/rte.lib.mk diff --git a/lib/librte_bitratestats/rte_bitrate.c b/lib/librte_bitratestats/rte_bitrate.c new file mode 100644 index 0000000..d97a526 --- /dev/null +++ b/lib/librte_bitratestats/rte_bitrate.c @@ -0,0 +1,128 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <rte_common.h> +#include <rte_ethdev.h> +#include <rte_malloc.h> +#include <rte_metrics.h> +#include <rte_bitrate.h> + +/* + * Persistent bit-rate data. + * @internal + */ +struct rte_stats_bitrate_s { + uint64_t last_ibytes; + uint64_t last_obytes; + uint64_t peak_ibits; + uint64_t peak_obits; + uint64_t ewma_ibits; + uint64_t ewma_obits; +}; + +struct rte_stats_bitrates_s { + struct rte_stats_bitrate_s port_stats[RTE_MAX_ETHPORTS]; + uint16_t id_stats_set; +}; + + +struct rte_stats_bitrates_s * +rte_stats_bitrate_create(void) +{ + return rte_zmalloc(NULL, sizeof(struct rte_stats_bitrates_s), 0); +} + + +int +rte_stats_bitrate_reg(struct rte_stats_bitrates_s *bitrate_data) +{ + const char *names[] = { + "mean_bits_in", "mean_bits_out", + "peak_bits_in", "peak_bits_out", + }; + int return_value; + + return_value = rte_metrics_reg_metrics(&names[0], 4); + if (return_value >= 0) + bitrate_data->id_stats_set = return_value; + return return_value; +} + + +int +rte_stats_bitrate_calc(struct rte_stats_bitrates_s *bitrate_data, + uint8_t port_id) +{ + struct rte_stats_bitrate_s *port_data; + struct rte_eth_stats eth_stats; + int ret_code; + uint64_t cnt_bits; + int64_t delta; + const int64_t alpha_percent = 20; + uint64_t values[4]; + + ret_code = rte_eth_stats_get(port_id, ð_stats); + if (ret_code != 0) + return ret_code; + + port_data = &bitrate_data->port_stats[port_id]; + + /* Incoming */ + cnt_bits = (eth_stats.ibytes - port_data->last_ibytes) << 3; + port_data->last_ibytes = eth_stats.ibytes; + if (cnt_bits > port_data->peak_ibits) + port_data->peak_ibits = cnt_bits; + delta = cnt_bits; + delta -= port_data->ewma_ibits; + /* The +50 fixes integer rounding during divison */ + delta = (delta * alpha_percent + 50) / 100; + port_data->ewma_ibits += delta; + + /* Outgoing */ + cnt_bits = (eth_stats.obytes - port_data->last_obytes) << 3; + port_data->last_obytes = eth_stats.obytes; + if (cnt_bits > port_data->peak_obits) + port_data->peak_obits = cnt_bits; + delta = cnt_bits; + delta -= port_data->ewma_obits; + delta = (delta * alpha_percent + 50) / 100; + port_data->ewma_obits += delta; + + values[0] = port_data->ewma_ibits; + values[1] = port_data->ewma_obits; + values[2] = port_data->peak_ibits; + values[3] = port_data->peak_obits; + rte_metrics_update_metrics(port_id, bitrate_data->id_stats_set, + values, 4); + return 0; +} diff --git a/lib/librte_bitratestats/rte_bitrate.h b/lib/librte_bitratestats/rte_bitrate.h new file mode 100644 index 0000000..cd566d6 --- /dev/null +++ b/lib/librte_bitratestats/rte_bitrate.h @@ -0,0 +1,80 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + + +/** + * Bitrate statistics data structure + */ +struct rte_stats_bitrates_s; + + +/** + * Allocate a bitrate statistics structure + * + * @return + * - Pointer to structure on success + * - NULL on error (zmalloc failure) + */ +struct rte_stats_bitrates_s *rte_stats_bitrate_create(void); + + +/** + * Register bitrate statistics + * + * @param bitrate_data + * Pointer allocated by rte_stats_create() + * + * @return + * Zero on success + * Negative on error + */ +int rte_stats_bitrate_reg(struct rte_stats_bitrates_s *bitrate_data); + + +/** + * Calculate statistics for current time window. The period this function + * is called should be the intended time window width. + * + * @param bitrate_data + * Bitrate statistics data pointer + * + * @param port_id + * Port id to calculate statistics for + * + * @return + * - Zero on success + * - Negative value on error + */ +int rte_stats_bitrate_calc(struct rte_stats_bitrates_s *bitrate_data, + uint8_t port_id); diff --git a/lib/librte_bitratestats/rte_bitratestats_version.map b/lib/librte_bitratestats/rte_bitratestats_version.map new file mode 100644 index 0000000..9de6be9 --- /dev/null +++ b/lib/librte_bitratestats/rte_bitratestats_version.map @@ -0,0 +1,9 @@ +DPDK_16.11 { + global: + + rte_stats_bitrate_calc; + rte_stats_bitrate_create; + rte_stats_bitrate_reg; + + local: *; +}; diff --git a/mk/rte.app.mk b/mk/rte.app.mk index 2db5427..5b5e547 100644 --- a/mk/rte.app.mk +++ b/mk/rte.app.mk @@ -99,6 +99,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL) += -lrte_eal _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE) += -lrte_cmdline _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE) += -lrte_cfgfile _LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS) += -lrte_metrics +_LDLIBS-$(CONFIG_RTE_LIBRTE_BITRATE) += -lrte_bitratestats _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += -lrte_pmd_bond -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v3 3/3] app/test-pmd: add support for bitrate statistics 2016-11-04 3:36 ` [dpdk-dev] [PATCH v3 0/3] Expanded statistics reporting Remy Horton 2016-11-04 3:36 ` [dpdk-dev] [PATCH v3 1/3] lib: add information metrics library Remy Horton 2016-11-04 3:36 ` [dpdk-dev] [PATCH v3 2/3] lib: add bitrate statistics library Remy Horton @ 2016-11-04 3:36 ` Remy Horton 2016-11-15 7:15 ` [dpdk-dev] [PATCH v4 0/3] Expanded statistics reporting Remy Horton 3 siblings, 0 replies; 115+ messages in thread From: Remy Horton @ 2016-11-04 3:36 UTC (permalink / raw) To: dev Signed-off-by: Remy Horton <remy.horton@intel.com> --- app/test-pmd/testpmd.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c index 6185be6..3cf4795 100644 --- a/app/test-pmd/testpmd.c +++ b/app/test-pmd/testpmd.c @@ -78,6 +78,8 @@ #ifdef RTE_LIBRTE_PDUMP #include <rte_pdump.h> #endif +#include <rte_metrics.h> +#include <rte_bitrate.h> #include "testpmd.h" @@ -322,6 +324,9 @@ uint16_t nb_rx_queue_stats_mappings = 0; unsigned max_socket = 0; +/* Bitrate statistics */ +struct rte_stats_bitrates_s *bitrate_data; + /* Forward function declarations */ static void map_port_queue_stats_mapping_registers(uint8_t pi, struct rte_port *port); static void check_all_ports_link_status(uint32_t port_mask); @@ -921,12 +926,26 @@ run_pkt_fwd_on_lcore(struct fwd_lcore *fc, packet_fwd_t pkt_fwd) struct fwd_stream **fsm; streamid_t nb_fs; streamid_t sm_id; - + uint64_t tics_per_1sec; + uint64_t tics_datum; + uint64_t tics_current; + uint8_t idx_port, cnt_ports; + + cnt_ports = rte_eth_dev_count(); + tics_datum = rte_rdtsc(); + tics_per_1sec = rte_get_timer_hz(); fsm = &fwd_streams[fc->stream_idx]; nb_fs = fc->stream_nb; do { for (sm_id = 0; sm_id < nb_fs; sm_id++) (*pkt_fwd)(fsm[sm_id]); + tics_current = rte_rdtsc(); + if (tics_current - tics_datum >= tics_per_1sec) { + /* Periodic bitrate calculation */ + for (idx_port = 0; idx_port < cnt_ports; idx_port++) + rte_stats_bitrate_calc(bitrate_data, idx_port); + tics_datum = tics_current; + } } while (! fc->stopped); } @@ -2128,6 +2147,13 @@ main(int argc, char** argv) FOREACH_PORT(port_id, ports) rte_eth_promiscuous_enable(port_id); + /* Setup bitrate stats */ + bitrate_data = rte_stats_bitrate_create(); + if (bitrate_data == NULL) + rte_exit(EXIT_FAILURE, "Could not allocate bitrate data.\n"); + rte_stats_bitrate_reg(bitrate_data); + + #ifdef RTE_LIBRTE_CMDLINE if (interactive == 1) { if (auto_start) { -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v4 0/3] Expanded statistics reporting 2016-11-04 3:36 ` [dpdk-dev] [PATCH v3 0/3] Expanded statistics reporting Remy Horton ` (2 preceding siblings ...) 2016-11-04 3:36 ` [dpdk-dev] [PATCH v3 3/3] app/test-pmd: add support for bitrate statistics Remy Horton @ 2016-11-15 7:15 ` Remy Horton 2016-11-15 7:15 ` [dpdk-dev] [PATCH v4 1/3] lib: add information metrics library Remy Horton ` (3 more replies) 3 siblings, 4 replies; 115+ messages in thread From: Remy Horton @ 2016-11-15 7:15 UTC (permalink / raw) To: dev; +Cc: thomas.monjalon This patchset extends statistics reporting to include peak and average data-rate metrics. It comes in two parts: a statistics reporting library, and a bitrate calculation library that uses it. This structure is intended to seperate statistic reporting from ethdev and allow more flexible metric registration. -- v4 changes: * References to 16.11 changed to 17.02 * Fetching of non-port values was broken * Added sanity checks to value fetching * rte_stat_value renamed to rte_metric_value * Corrected doxygen descriptions * Added MAINTAINERS entries * Added #ifdef directives to bitrate code in test-pmd v3 changes: * Marked rte_stats_bitrate_s as internal * Minor integer roundoff correction * Coding style corrections * Removed spurious object allocation * Changes to rte_metrics.[ch] moved from Patch 2/3 to 1/3. * Reintroduced non-port values (RTE_METRICS_NONPORT) * Added spinlocks to metric library * Removed spurious test registration/update * Added release notes entries v2 changes: * Uses a new metrics library rather than being part of ethdev Remy Horton (3): lib: add information metrics library lib: add bitrate statistics library app/test-pmd: add support for bitrate statistics MAINTAINERS | 9 + app/test-pmd/testpmd.c | 36 +++ config/common_base | 10 + doc/api/doxy-api-index.md | 2 + doc/api/doxy-api.conf | 2 + doc/guides/rel_notes/release_17_02.rst | 11 + lib/Makefile | 2 + lib/librte_bitratestats/Makefile | 53 ++++ lib/librte_bitratestats/rte_bitrate.c | 128 +++++++++ lib/librte_bitratestats/rte_bitrate.h | 80 ++++++ .../rte_bitratestats_version.map | 9 + lib/librte_metrics/Makefile | 51 ++++ lib/librte_metrics/rte_metrics.c | 308 +++++++++++++++++++++ lib/librte_metrics/rte_metrics.h | 190 +++++++++++++ lib/librte_metrics/rte_metrics_version.map | 13 + mk/rte.app.mk | 3 + 16 files changed, 907 insertions(+) create mode 100644 lib/librte_bitratestats/Makefile create mode 100644 lib/librte_bitratestats/rte_bitrate.c create mode 100644 lib/librte_bitratestats/rte_bitrate.h create mode 100644 lib/librte_bitratestats/rte_bitratestats_version.map create mode 100644 lib/librte_metrics/Makefile create mode 100644 lib/librte_metrics/rte_metrics.c create mode 100644 lib/librte_metrics/rte_metrics.h create mode 100644 lib/librte_metrics/rte_metrics_version.map -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v4 1/3] lib: add information metrics library 2016-11-15 7:15 ` [dpdk-dev] [PATCH v4 0/3] Expanded statistics reporting Remy Horton @ 2016-11-15 7:15 ` Remy Horton 2016-11-15 7:15 ` [dpdk-dev] [PATCH v4 2/3] lib: add bitrate statistics library Remy Horton ` (2 subsequent siblings) 3 siblings, 0 replies; 115+ messages in thread From: Remy Horton @ 2016-11-15 7:15 UTC (permalink / raw) To: dev; +Cc: thomas.monjalon This patch adds a new information metric library that allows other modules to register named metrics and update their values. It is intended to be independent of ethdev, rather than mixing ethdev and non-ethdev information in xstats. Signed-off-by: Remy Horton <remy.horton@intel.com> --- MAINTAINERS | 5 + config/common_base | 5 + doc/api/doxy-api-index.md | 1 + doc/api/doxy-api.conf | 1 + doc/guides/rel_notes/release_17_02.rst | 6 + lib/Makefile | 1 + lib/librte_metrics/Makefile | 51 +++++ lib/librte_metrics/rte_metrics.c | 308 +++++++++++++++++++++++++++++ lib/librte_metrics/rte_metrics.h | 190 ++++++++++++++++++ lib/librte_metrics/rte_metrics_version.map | 13 ++ mk/rte.app.mk | 2 + 11 files changed, 583 insertions(+) create mode 100644 lib/librte_metrics/Makefile create mode 100644 lib/librte_metrics/rte_metrics.c create mode 100644 lib/librte_metrics/rte_metrics.h create mode 100644 lib/librte_metrics/rte_metrics_version.map diff --git a/MAINTAINERS b/MAINTAINERS index d6bb8f8..52bd8a9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -595,6 +595,11 @@ F: lib/librte_jobstats/ F: examples/l2fwd-jobstats/ F: doc/guides/sample_app_ug/l2_forward_job_stats.rst +Metrics +M: Remy Horton <remy.horton@intel.com> +F: lib/librte_metrics/ +F: doc/guides/sample_app_ug/keep_alive.rst + Test Applications ----------------- diff --git a/config/common_base b/config/common_base index 4bff83a..dedc4c3 100644 --- a/config/common_base +++ b/config/common_base @@ -589,3 +589,8 @@ CONFIG_RTE_APP_TEST_RESOURCE_TAR=n CONFIG_RTE_TEST_PMD=y CONFIG_RTE_TEST_PMD_RECORD_CORE_CYCLES=n CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n + +# +# Compile the device metrics library +# +CONFIG_RTE_LIBRTE_METRICS=y diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md index 6675f96..ca50fa6 100644 --- a/doc/api/doxy-api-index.md +++ b/doc/api/doxy-api-index.md @@ -147,4 +147,5 @@ There are many libraries, so their headers may be grouped by topics: [common] (@ref rte_common.h), [ABI compat] (@ref rte_compat.h), [keepalive] (@ref rte_keepalive.h), + [Device Metrics] (@ref rte_metrics.h), [version] (@ref rte_version.h) diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf index 9dc7ae5..fe830eb 100644 --- a/doc/api/doxy-api.conf +++ b/doc/api/doxy-api.conf @@ -57,6 +57,7 @@ INPUT = doc/api/doxy-api-index.md \ lib/librte_reorder \ lib/librte_ring \ lib/librte_sched \ + lib/librte_metrics \ lib/librte_table \ lib/librte_timer \ lib/librte_vhost diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst index 3b65038..e1b8894 100644 --- a/doc/guides/rel_notes/release_17_02.rst +++ b/doc/guides/rel_notes/release_17_02.rst @@ -34,6 +34,12 @@ New Features Refer to the previous release notes for examples. + * **Added information metric library.** + + A library that allows information metrics to be added and update. It is + intended to provide a reporting mechanism that is independent of the + ethdev library. + This section is a comment. do not overwrite or remove it. Also, make sure to start the actual text at the margin. ========================================================= diff --git a/lib/Makefile b/lib/Makefile index 990f23a..5d85dcf 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -58,6 +58,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_TABLE) += librte_table DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += librte_pipeline DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump +DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni diff --git a/lib/librte_metrics/Makefile b/lib/librte_metrics/Makefile new file mode 100644 index 0000000..8d6e23a --- /dev/null +++ b/lib/librte_metrics/Makefile @@ -0,0 +1,51 @@ +# BSD LICENSE +# +# Copyright(c) 2016 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +include $(RTE_SDK)/mk/rte.vars.mk + +# library name +LIB = librte_metrics.a + +CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) + +EXPORT_MAP := rte_metrics_version.map + +LIBABIVER := 1 + +# all source are stored in SRCS-y +SRCS-$(CONFIG_RTE_LIBRTE_METRICS) := rte_metrics.c + +# Install header file +SYMLINK-$(CONFIG_RTE_LIBRTE_METRICS)-include += rte_metrics.h + +DEPDIRS-$(CONFIG_RTE_LIBRTE_METRICS) += lib/librte_eal + +include $(RTE_SDK)/mk/rte.lib.mk diff --git a/lib/librte_metrics/rte_metrics.c b/lib/librte_metrics/rte_metrics.c new file mode 100644 index 0000000..5edacc6 --- /dev/null +++ b/lib/librte_metrics/rte_metrics.c @@ -0,0 +1,308 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <string.h> +#include <sys/queue.h> + +#include <rte_common.h> +#include <rte_malloc.h> +#include <rte_metrics.h> +#include <rte_lcore.h> +#include <rte_memzone.h> +#include <rte_spinlock.h> + +#define RTE_METRICS_MAX_METRICS 256 +#define RTE_METRICS_MEMZONE_NAME "RTE_METRICS" + +/** + * Internal stats metadata and value entry. + * + * @internal + * @param name + * Name of metric + * @param value + * Current value for metric + * @param idx_next_set + * Index of next root element (zero for none) + * @param idx_next_metric + * Index of next metric in set (zero for none) + * + * Only the root of each set needs idx_next_set but since it has to be + * assumed that number of sets could equal total number of metrics, + * having a separate set metadata table doesn't save any memory. + */ +struct rte_metrics_meta_s { + char name[RTE_METRICS_MAX_NAME_LEN]; + uint64_t value[RTE_MAX_ETHPORTS]; + uint64_t nonport_value; + uint16_t idx_next_set; + uint16_t idx_next_stat; +}; + +/** + * Internal stats info structure. + * + * @internal + * @param idx_last_set + * Index of last metadata entry with valid data. This value is + * not valid if cnt_stats is zero. + * @param cnt_stats + * Number of metrics. + * @param metadata + * Stat data memory block. + * + * Offsets into metadata are used instead of pointers because ASLR + * means that having the same physical addresses in different + * processes is not guaranteed. + */ +struct rte_metrics_data_s { + uint16_t idx_last_set; + uint16_t cnt_stats; + struct rte_metrics_meta_s metadata[RTE_METRICS_MAX_METRICS]; + rte_spinlock_t lock; +}; + +void +rte_metrics_init(void) +{ + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + + if (rte_eal_process_type() != RTE_PROC_PRIMARY) + return; + + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); + if (memzone != NULL) + return; + memzone = rte_memzone_reserve(RTE_METRICS_MEMZONE_NAME, + sizeof(struct rte_metrics_data_s), rte_socket_id(), 0); + if (memzone == NULL) + rte_exit(EXIT_FAILURE, "Unable to allocate stats memzone\n"); + stats = memzone->addr; + memset(stats, 0, sizeof(struct rte_metrics_data_s)); + rte_spinlock_init(&stats->lock); +} + +int +rte_metrics_reg_metric(const char *name) +{ + const char *list_names[] = {name}; + + return rte_metrics_reg_metrics(list_names, 1); +} + +int +rte_metrics_reg_metrics(const char **names, uint16_t cnt_names) +{ + struct rte_metrics_meta_s *entry; + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + uint16_t idx_name; + uint16_t idx_base; + + /* Some sanity checks */ + if (cnt_names < 1 || names == NULL) + return -EINVAL; + + rte_metrics_init(); + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); + if (memzone == NULL) + return -EIO; + stats = memzone->addr; + + if (stats->cnt_stats + cnt_names >= RTE_METRICS_MAX_METRICS) + return -ENOMEM; + + rte_spinlock_lock(&stats->lock); + + /* Overwritten later if this is actually first set.. */ + stats->metadata[stats->idx_last_set].idx_next_set = stats->cnt_stats; + + stats->idx_last_set = idx_base = stats->cnt_stats; + + for (idx_name = 0; idx_name < cnt_names; idx_name++) { + entry = &stats->metadata[idx_name + stats->cnt_stats]; + strncpy(entry->name, names[idx_name], + RTE_METRICS_MAX_NAME_LEN); + memset(entry->value, 0, sizeof(entry->value)); + entry->idx_next_stat = idx_name + stats->cnt_stats + 1; + } + entry->idx_next_stat = 0; + entry->idx_next_set = 0; + stats->cnt_stats += cnt_names; + + rte_spinlock_unlock(&stats->lock); + + return idx_base; +} + +int +rte_metrics_update_metric(int port_id, uint16_t key, const uint64_t value) +{ + return rte_metrics_update_metrics(port_id, key, &value, 1); +} + +int +rte_metrics_update_metrics(int port_id, + uint16_t key, + const uint64_t *values, + uint32_t count) +{ + struct rte_metrics_meta_s *entry; + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + uint16_t idx_metric; + uint16_t idx_value; + uint16_t cnt_setsize; + + if (port_id != RTE_METRICS_NONPORT && + (port_id < 0 || port_id > RTE_MAX_ETHPORTS)) + return -EINVAL; + + rte_metrics_init(); + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); + if (memzone == NULL) + return -EIO; + stats = memzone->addr; + + rte_spinlock_lock(&stats->lock); + idx_metric = key; + cnt_setsize = 1; + while (idx_metric < stats->cnt_stats) { + entry = &stats->metadata[idx_metric]; + if (entry->idx_next_stat == 0) + break; + cnt_setsize++; + idx_metric++; + } + /* Check update does not cross set border */ + if (count > cnt_setsize) { + rte_spinlock_unlock(&stats->lock); + return -ERANGE; + } + + if (port_id == RTE_METRICS_NONPORT) + for (idx_value = 0; idx_value < count; idx_value++) { + idx_metric = key + idx_value; + stats->metadata[idx_metric].nonport_value = + values[idx_value]; + } + else + for (idx_value = 0; idx_value < count; idx_value++) { + idx_metric = key + idx_value; + stats->metadata[idx_metric].value[port_id] = + values[idx_value]; + } + rte_spinlock_unlock(&stats->lock); + return 0; +} + +int +rte_metrics_get_names(struct rte_metric_name *names, + uint16_t capacity) +{ + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + uint16_t idx_name; + int return_value; + + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); + /* If not allocated, fail silently */ + if (memzone == NULL) + return 0; + + stats = memzone->addr; + rte_spinlock_lock(&stats->lock); + if (names != NULL) { + if (capacity < stats->cnt_stats) { + rte_spinlock_unlock(&stats->lock); + return -ERANGE; + } + for (idx_name = 0; idx_name < stats->cnt_stats; idx_name++) + strncpy(names[idx_name].name, + stats->metadata[idx_name].name, + RTE_METRICS_MAX_NAME_LEN); + } + return_value = stats->cnt_stats; + rte_spinlock_unlock(&stats->lock); + return return_value; +} + +int +rte_metrics_get_values(int port_id, + struct rte_metric_value *values, + uint16_t capacity) +{ + struct rte_metrics_meta_s *entry; + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + uint16_t idx_name; + int return_value; + + if (port_id != RTE_METRICS_NONPORT && + (port_id < 0 || port_id > RTE_MAX_ETHPORTS)) + return -EINVAL; + + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); + /* If not allocated, fail silently */ + if (memzone == NULL) + return 0; + stats = memzone->addr; + rte_spinlock_lock(&stats->lock); + + if (values != NULL) { + if (capacity < stats->cnt_stats) { + rte_spinlock_unlock(&stats->lock); + return -ERANGE; + } + if (port_id == RTE_METRICS_NONPORT) + for (idx_name = 0; + idx_name < stats->cnt_stats; + idx_name++) { + entry = &stats->metadata[idx_name]; + values[idx_name].key = idx_name; + values[idx_name].value = entry->nonport_value; + } + else + for (idx_name = 0; + idx_name < stats->cnt_stats; + idx_name++) { + entry = &stats->metadata[idx_name]; + values[idx_name].key = idx_name; + values[idx_name].value = entry->value[port_id]; + } + } + return_value = stats->cnt_stats; + rte_spinlock_unlock(&stats->lock); + return return_value; +} diff --git a/lib/librte_metrics/rte_metrics.h b/lib/librte_metrics/rte_metrics.h new file mode 100644 index 0000000..c58b366 --- /dev/null +++ b/lib/librte_metrics/rte_metrics.h @@ -0,0 +1,190 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * + * RTE Metrics module + * + * Metric information is populated using a push model, where the + * information provider calls an update function on the relevant + * metrics. Currently only bulk querying of metrics is supported. + */ + +#ifndef _RTE_METRICS_H_ +#define _RTE_METRICS_H_ + +/** Maximum length of metric name (including null-terminator) */ +#define RTE_METRICS_MAX_NAME_LEN 64 + +/** Used to indicate port-independent information */ +#define RTE_METRICS_NONPORT -1 + + +/** + * Metric name + */ +struct rte_metric_name { + /** String describing metric */ + char name[RTE_METRICS_MAX_NAME_LEN]; +}; + + +/** + * Metric name. + */ +struct rte_metric_value { + /** Numeric identifier of metric */ + uint16_t key; + /** Value for metric */ + uint64_t value; +}; + + +/** + * Initializes metric module. This only has to be explicitly called if you + * intend to use rte_metrics_reg_metric() or rte_metrics_reg_metrics() from a + * secondary process. This function must be called from a primary process. + */ +void rte_metrics_init(void); + + +/** + * Register a metric + * + * @param name + * Metric name + * + * @return + * - Zero or positive: Success + * - Negative: Failure + */ +int rte_metrics_reg_metric(const char *name); + +/** + * Register a set of metrics + * + * @param names + * List of metric names + * + * @param cnt_names + * Number of metrics in set + * + * @return + * - Zero or positive: Success + * - Negative: Failure + */ +int rte_metrics_reg_metrics(const char **names, uint16_t cnt_names); + +/** + * Get metric name-key lookup table. + * + * @param names + * Array of names to receive key names + * + * @param capacity + * Space available in names + * + * @return + * - Non-negative: Success (number of names) + * - Negative: Failure + */ +int rte_metrics_get_names( + struct rte_metric_name *names, + uint16_t capacity); + +/** + * Fetch metrics. + * + * @param port_id + * Port id to query + * + * @param values + * Array to receive values and their keys + * + * @param capacity + * Space available in values + * + * @return + * - Non-negative: Success (number of names) + * - Negative: Failure + */ +int rte_metrics_get_values( + int port_id, + struct rte_metric_value *values, + uint16_t capacity); + +/** + * Updates a metric + * + * @param port_id + * Port to update metrics for + * @param key + * Id of metric to update + * @param value + * New value + * + * @return + * - -EIO if unable to access shared metrics memory + * - Zero on success + */ +int rte_metrics_update_metric( + int port_id, + uint16_t key, + const uint64_t value); + +/** + * Updates a metric set. Note that it is an error to try to + * update across a set boundary. + * + * @param port_id + * Port to update metrics for + * @param key + * Base id of metrics set to update + * @param values + * Set of new values + * @param count + * Number of new values + * + * @return + * - -ERANGE if count exceeds metric set size + * - -EIO if upable to access shared metrics memory + * - Zero on success + */ +int rte_metrics_update_metrics( + int port_id, + uint16_t key, + const uint64_t *values, + uint32_t count); + +#endif diff --git a/lib/librte_metrics/rte_metrics_version.map b/lib/librte_metrics/rte_metrics_version.map new file mode 100644 index 0000000..f904814 --- /dev/null +++ b/lib/librte_metrics/rte_metrics_version.map @@ -0,0 +1,13 @@ +DPDK_17.02 { + global: + + rte_metrics_get_names; + rte_metrics_get_values; + rte_metrics_init; + rte_metrics_reg_metric; + rte_metrics_reg_metrics; + rte_metrics_update_metric; + rte_metrics_update_metrics; + + local: *; +}; diff --git a/mk/rte.app.mk b/mk/rte.app.mk index f75f0e2..40fcf33 100644 --- a/mk/rte.app.mk +++ b/mk/rte.app.mk @@ -98,6 +98,8 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_RING) += -lrte_ring _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL) += -lrte_eal _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE) += -lrte_cmdline _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE) += -lrte_cfgfile +_LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS) += -lrte_metrics + _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += -lrte_pmd_bond _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += -lrte_pmd_xenvirt -lxenstore -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v4 2/3] lib: add bitrate statistics library 2016-11-15 7:15 ` [dpdk-dev] [PATCH v4 0/3] Expanded statistics reporting Remy Horton 2016-11-15 7:15 ` [dpdk-dev] [PATCH v4 1/3] lib: add information metrics library Remy Horton @ 2016-11-15 7:15 ` Remy Horton 2016-11-15 15:17 ` Pattan, Reshma 2016-11-15 7:15 ` [dpdk-dev] [PATCH v4 3/3] app/test-pmd: add support for bitrate statistics Remy Horton 2016-11-18 8:00 ` [dpdk-dev] [PATCH v5 0/4] Expanded statistics reporting Remy Horton 3 siblings, 1 reply; 115+ messages in thread From: Remy Horton @ 2016-11-15 7:15 UTC (permalink / raw) To: dev; +Cc: thomas.monjalon This patch adds a library that calculates peak and average data-rate statistics. For ethernet devices. These statistics are reported using the metrics library. Signed-off-by: Remy Horton <remy.horton@intel.com> --- MAINTAINERS | 4 + config/common_base | 5 + doc/api/doxy-api-index.md | 1 + doc/api/doxy-api.conf | 1 + doc/guides/rel_notes/release_17_02.rst | 5 + lib/Makefile | 1 + lib/librte_bitratestats/Makefile | 53 +++++++++ lib/librte_bitratestats/rte_bitrate.c | 128 +++++++++++++++++++++ lib/librte_bitratestats/rte_bitrate.h | 80 +++++++++++++ .../rte_bitratestats_version.map | 9 ++ mk/rte.app.mk | 1 + 11 files changed, 288 insertions(+) create mode 100644 lib/librte_bitratestats/Makefile create mode 100644 lib/librte_bitratestats/rte_bitrate.c create mode 100644 lib/librte_bitratestats/rte_bitrate.h create mode 100644 lib/librte_bitratestats/rte_bitratestats_version.map diff --git a/MAINTAINERS b/MAINTAINERS index 52bd8a9..d6bbdd5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -600,6 +600,10 @@ M: Remy Horton <remy.horton@intel.com> F: lib/librte_metrics/ F: doc/guides/sample_app_ug/keep_alive.rst +Bit-rate statistica +M: Remy Horton <remy.horton@intel.com> +F: lib/librte_bitratestats/ + Test Applications ----------------- diff --git a/config/common_base b/config/common_base index dedc4c3..beca7ec 100644 --- a/config/common_base +++ b/config/common_base @@ -594,3 +594,8 @@ CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n # Compile the device metrics library # CONFIG_RTE_LIBRTE_METRICS=y + +# +# Compile the bitrate statistics library +# +CONFIG_RTE_LIBRTE_BITRATE=y diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md index ca50fa6..91e8ea6 100644 --- a/doc/api/doxy-api-index.md +++ b/doc/api/doxy-api-index.md @@ -148,4 +148,5 @@ There are many libraries, so their headers may be grouped by topics: [ABI compat] (@ref rte_compat.h), [keepalive] (@ref rte_keepalive.h), [Device Metrics] (@ref rte_metrics.h), + [Bitrate Statistics] (@ref rte_bitrate.h), [version] (@ref rte_version.h) diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf index fe830eb..8765ddd 100644 --- a/doc/api/doxy-api.conf +++ b/doc/api/doxy-api.conf @@ -58,6 +58,7 @@ INPUT = doc/api/doxy-api-index.md \ lib/librte_ring \ lib/librte_sched \ lib/librte_metrics \ + lib/librte_bitratestats \ lib/librte_table \ lib/librte_timer \ lib/librte_vhost diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst index e1b8894..f949e88 100644 --- a/doc/guides/rel_notes/release_17_02.rst +++ b/doc/guides/rel_notes/release_17_02.rst @@ -40,6 +40,11 @@ New Features intended to provide a reporting mechanism that is independent of the ethdev library. + * **Added bit-rate calculation library.** + + A library that can be used to calculate device bit-rates. Calculated + bitrates are reported using the metrics library. + This section is a comment. do not overwrite or remove it. Also, make sure to start the actual text at the margin. ========================================================= diff --git a/lib/Makefile b/lib/Makefile index 5d85dcf..e211bc0 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -59,6 +59,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += librte_pipeline DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics +DIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += librte_bitratestats ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni diff --git a/lib/librte_bitratestats/Makefile b/lib/librte_bitratestats/Makefile new file mode 100644 index 0000000..b725d4e --- /dev/null +++ b/lib/librte_bitratestats/Makefile @@ -0,0 +1,53 @@ +# BSD LICENSE +# +# Copyright(c) 2016 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +include $(RTE_SDK)/mk/rte.vars.mk + +# library name +LIB = librte_bitratestats.a + +CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) + +EXPORT_MAP := rte_bitratestats_version.map + +LIBABIVER := 1 + +# all source are stored in SRCS-y +SRCS-$(CONFIG_RTE_LIBRTE_BITRATE) := rte_bitrate.c + +# Install header file +SYMLINK-$(CONFIG_RTE_LIBRTE_BITRATE)-include += rte_bitrate.h + +DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_eal +DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_ether +DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_metrics + +include $(RTE_SDK)/mk/rte.lib.mk diff --git a/lib/librte_bitratestats/rte_bitrate.c b/lib/librte_bitratestats/rte_bitrate.c new file mode 100644 index 0000000..6346bb1 --- /dev/null +++ b/lib/librte_bitratestats/rte_bitrate.c @@ -0,0 +1,128 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <rte_common.h> +#include <rte_ethdev.h> +#include <rte_malloc.h> +#include <rte_metrics.h> +#include <rte_bitrate.h> + +/* + * Persistent bit-rate data. + * @internal + */ +struct rte_stats_bitrate_s { + uint64_t last_ibytes; + uint64_t last_obytes; + uint64_t peak_ibits; + uint64_t peak_obits; + uint64_t ewma_ibits; + uint64_t ewma_obits; +}; + +struct rte_stats_bitrates_s { + struct rte_stats_bitrate_s port_stats[RTE_MAX_ETHPORTS]; + uint16_t id_stats_set; +}; + +struct rte_stats_bitrates_s * +rte_stats_bitrate_create(void) +{ + return rte_zmalloc(NULL, sizeof(struct rte_stats_bitrates_s), 0); +} + +int +rte_stats_bitrate_reg(struct rte_stats_bitrates_s *bitrate_data) +{ + const char *names[] = { + "mean_bits_in", "mean_bits_out", + "peak_bits_in", "peak_bits_out", + }; + int return_value; + + return_value = rte_metrics_reg_metrics(&names[0], 4); + if (return_value >= 0) + bitrate_data->id_stats_set = return_value; + return return_value; +} + +int +rte_stats_bitrate_calc(struct rte_stats_bitrates_s *bitrate_data, + uint8_t port_id) +{ + struct rte_stats_bitrate_s *port_data; + struct rte_eth_stats eth_stats; + int ret_code; + uint64_t cnt_bits; + int64_t delta; + const int64_t alpha_percent = 20; + uint64_t values[4]; + + ret_code = rte_eth_stats_get(port_id, ð_stats); + if (ret_code != 0) + return ret_code; + + port_data = &bitrate_data->port_stats[port_id]; + + /* Incoming bitrate. This is an iteratively calculated EWMA + * (Expomentially Weighted Moving Average) that uses a + * weighting factor of alpha_percent. + */ + cnt_bits = (eth_stats.ibytes - port_data->last_ibytes) << 3; + port_data->last_ibytes = eth_stats.ibytes; + if (cnt_bits > port_data->peak_ibits) + port_data->peak_ibits = cnt_bits; + delta = cnt_bits; + delta -= port_data->ewma_ibits; + /* The +50 fixes integer rounding during divison */ + delta = (delta * alpha_percent + 50) / 100; + port_data->ewma_ibits += delta; + + /* Outgoing bitrate (also EWMA) */ + cnt_bits = (eth_stats.obytes - port_data->last_obytes) << 3; + port_data->last_obytes = eth_stats.obytes; + if (cnt_bits > port_data->peak_obits) + port_data->peak_obits = cnt_bits; + delta = cnt_bits; + delta -= port_data->ewma_obits; + delta = (delta * alpha_percent + 50) / 100; + port_data->ewma_obits += delta; + + values[0] = port_data->ewma_ibits; + values[1] = port_data->ewma_obits; + values[2] = port_data->peak_ibits; + values[3] = port_data->peak_obits; + rte_metrics_update_metrics(port_id, bitrate_data->id_stats_set, + values, 4); + return 0; +} diff --git a/lib/librte_bitratestats/rte_bitrate.h b/lib/librte_bitratestats/rte_bitrate.h new file mode 100644 index 0000000..bc87c5e --- /dev/null +++ b/lib/librte_bitratestats/rte_bitrate.h @@ -0,0 +1,80 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +/** + * Bitrate statistics data structure. + * This data structure is intentionally opaque. + */ +struct rte_stats_bitrates_s; + + +/** + * Allocate a bitrate statistics structure + * + * @return + * - Pointer to structure on success + * - NULL on error (zmalloc failure) + */ +struct rte_stats_bitrates_s *rte_stats_bitrate_create(void); + + +/** + * Register bitrate statistics with the metric library. + * + * @param bitrate_data + * Pointer allocated by rte_stats_create() + * + * @return + * Zero on success + * Negative on error + */ +int rte_stats_bitrate_reg(struct rte_stats_bitrates_s *bitrate_data); + + +/** + * Calculate statistics for current time window. The period with which + * this function is called should be the intended sampling window width. + * + * @param bitrate_data + * Bitrate statistics data pointer + * + * @param port_id + * Port id to calculate statistics for + * + * @return + * - Zero on success + * - Negative value on error + */ +int rte_stats_bitrate_calc(struct rte_stats_bitrates_s *bitrate_data, + uint8_t port_id); diff --git a/lib/librte_bitratestats/rte_bitratestats_version.map b/lib/librte_bitratestats/rte_bitratestats_version.map new file mode 100644 index 0000000..66f232f --- /dev/null +++ b/lib/librte_bitratestats/rte_bitratestats_version.map @@ -0,0 +1,9 @@ +DPDK_17.02 { + global: + + rte_stats_bitrate_calc; + rte_stats_bitrate_create; + rte_stats_bitrate_reg; + + local: *; +}; diff --git a/mk/rte.app.mk b/mk/rte.app.mk index 40fcf33..6aac5ac 100644 --- a/mk/rte.app.mk +++ b/mk/rte.app.mk @@ -99,6 +99,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL) += -lrte_eal _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE) += -lrte_cmdline _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE) += -lrte_cfgfile _LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS) += -lrte_metrics +_LDLIBS-$(CONFIG_RTE_LIBRTE_BITRATE) += -lrte_bitratestats _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += -lrte_pmd_bond -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [PATCH v4 2/3] lib: add bitrate statistics library 2016-11-15 7:15 ` [dpdk-dev] [PATCH v4 2/3] lib: add bitrate statistics library Remy Horton @ 2016-11-15 15:17 ` Pattan, Reshma 0 siblings, 0 replies; 115+ messages in thread From: Pattan, Reshma @ 2016-11-15 15:17 UTC (permalink / raw) To: Horton, Remy; +Cc: thomas.monjalon, dev Hi, > Signed-off-by: Remy Horton <remy.horton@intel.com> > --- > a/doc/guides/rel_notes/release_17_02.rst > b/doc/guides/rel_notes/release_17_02.rst > index e1b8894..f949e88 100644 > --- a/doc/guides/rel_notes/release_17_02.rst > +++ b/doc/guides/rel_notes/release_17_02.rst > @@ -40,6 +40,11 @@ New Features > intended to provide a reporting mechanism that is independent of the > ethdev library. > > + * **Added bit-rate calculation library.** > + > + A library that can be used to calculate device bit-rates. Calculated > + bitrates are reported using the metrics library. > + Shared Library Versions section also need to be updated for bitrate and metrics libraries. Thanks, Reshma ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v4 3/3] app/test-pmd: add support for bitrate statistics 2016-11-15 7:15 ` [dpdk-dev] [PATCH v4 0/3] Expanded statistics reporting Remy Horton 2016-11-15 7:15 ` [dpdk-dev] [PATCH v4 1/3] lib: add information metrics library Remy Horton 2016-11-15 7:15 ` [dpdk-dev] [PATCH v4 2/3] lib: add bitrate statistics library Remy Horton @ 2016-11-15 7:15 ` Remy Horton 2016-11-18 8:00 ` [dpdk-dev] [PATCH v5 0/4] Expanded statistics reporting Remy Horton 3 siblings, 0 replies; 115+ messages in thread From: Remy Horton @ 2016-11-15 7:15 UTC (permalink / raw) To: dev; +Cc: thomas.monjalon Signed-off-by: Remy Horton <remy.horton@intel.com> --- app/test-pmd/testpmd.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c index a0332c2..60c635f 100644 --- a/app/test-pmd/testpmd.c +++ b/app/test-pmd/testpmd.c @@ -78,6 +78,10 @@ #ifdef RTE_LIBRTE_PDUMP #include <rte_pdump.h> #endif +#include <rte_metrics.h> +#ifdef RTE_LIBRTE_BITRATE +#include <rte_bitrate.h> +#endif #include "testpmd.h" @@ -322,6 +326,9 @@ uint16_t nb_rx_queue_stats_mappings = 0; unsigned max_socket = 0; +/* Bitrate statistics */ +struct rte_stats_bitrates_s *bitrate_data; + /* Forward function declarations */ static void map_port_queue_stats_mapping_registers(uint8_t pi, struct rte_port *port); static void check_all_ports_link_status(uint32_t port_mask); @@ -921,12 +928,32 @@ run_pkt_fwd_on_lcore(struct fwd_lcore *fc, packet_fwd_t pkt_fwd) struct fwd_stream **fsm; streamid_t nb_fs; streamid_t sm_id; +#ifdef RTE_LIBRTE_BITRATE + uint64_t tics_per_1sec; + uint64_t tics_datum; + uint64_t tics_current; + uint8_t idx_port, cnt_ports; +#endif +#ifdef RTE_LIBRTE_BITRATE + cnt_ports = rte_eth_dev_count(); + tics_datum = rte_rdtsc(); + tics_per_1sec = rte_get_timer_hz(); +#endif fsm = &fwd_streams[fc->stream_idx]; nb_fs = fc->stream_nb; do { for (sm_id = 0; sm_id < nb_fs; sm_id++) (*pkt_fwd)(fsm[sm_id]); +#ifdef RTE_LIBRTE_BITRATE + tics_current = rte_rdtsc(); + if (tics_current - tics_datum >= tics_per_1sec) { + /* Periodic bitrate calculation */ + for (idx_port = 0; idx_port < cnt_ports; idx_port++) + rte_stats_bitrate_calc(bitrate_data, idx_port); + tics_datum = tics_current; + } +#endif } while (! fc->stopped); } @@ -2133,6 +2160,15 @@ main(int argc, char** argv) FOREACH_PORT(port_id, ports) rte_eth_promiscuous_enable(port_id); + /* Setup bitrate stats */ +#ifdef RTE_LIBRTE_BITRATE + bitrate_data = rte_stats_bitrate_create(); + if (bitrate_data == NULL) + rte_exit(EXIT_FAILURE, "Could not allocate bitrate data.\n"); + rte_stats_bitrate_reg(bitrate_data); +#endif + + #ifdef RTE_LIBRTE_CMDLINE if (interactive == 1) { if (auto_start) { -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v5 0/4] Expanded statistics reporting 2016-11-15 7:15 ` [dpdk-dev] [PATCH v4 0/3] Expanded statistics reporting Remy Horton ` (2 preceding siblings ...) 2016-11-15 7:15 ` [dpdk-dev] [PATCH v4 3/3] app/test-pmd: add support for bitrate statistics Remy Horton @ 2016-11-18 8:00 ` Remy Horton 2016-11-18 8:00 ` [dpdk-dev] [PATCH v5 1/4] lib: add information metrics library Remy Horton ` (4 more replies) 3 siblings, 5 replies; 115+ messages in thread From: Remy Horton @ 2016-11-18 8:00 UTC (permalink / raw) To: dev; +Cc: Thomas Monjalon This patchset extends statistics reporting to include peak and average data-rate metrics. It comes in two parts: a statistics reporting library, and a bitrate calculation library that uses it. This structure is intended to seperate statistic reporting from ethdev and allow more flexible metric registration. Due to merge issues Reshma's latency statistics, which depends on the reporting library, has been merged into this patchset. -- v5 changes: * Updated Shared Library Versions in release notes * Merged in Reshma's latencystats library v4 changes: * References to 16.11 changed to 17.02 * Fetching of non-port values was broken * Added sanity checks to value fetching * rte_stat_value renamed to rte_metric_value * Corrected doxygen descriptions * Added MAINTAINERS entries * Added #ifdef directives to bitrate code in test-pmd v3 changes: * Marked rte_stats_bitrate_s as internal * Minor integer roundoff correction * Coding style corrections * Removed spurious object allocation * Changes to rte_metrics.[ch] moved from Patch 2/3 to 1/3. * Reintroduced non-port values (RTE_METRICS_NONPORT) * Added spinlocks to metric library * Removed spurious test registration/update * Added release notes entries v2 changes: * Uses a new metrics library rather than being part of ethdev Remy Horton (4): lib: add information metrics library lib: add bitrate statistics library app/test-pmd: add support for bitrate statistics latencystats: added new library for latency stats MAINTAINERS | 13 + app/proc_info/main.c | 70 ++++ app/test-pmd/testpmd.c | 46 +++ config/common_base | 15 + doc/api/doxy-api-index.md | 3 + doc/api/doxy-api.conf | 3 + doc/guides/rel_notes/release_17_02.rst | 18 + lib/Makefile | 3 + lib/librte_bitratestats/Makefile | 53 +++ lib/librte_bitratestats/rte_bitrate.c | 128 +++++++ lib/librte_bitratestats/rte_bitrate.h | 80 +++++ .../rte_bitratestats_version.map | 9 + lib/librte_latencystats/Makefile | 57 +++ lib/librte_latencystats/rte_latencystats.c | 389 +++++++++++++++++++++ lib/librte_latencystats/rte_latencystats.h | 146 ++++++++ .../rte_latencystats_version.map | 10 + lib/librte_mbuf/rte_mbuf.h | 3 + lib/librte_metrics/Makefile | 51 +++ lib/librte_metrics/rte_metrics.c | 308 ++++++++++++++++ lib/librte_metrics/rte_metrics.h | 190 ++++++++++ lib/librte_metrics/rte_metrics_version.map | 13 + mk/rte.app.mk | 3 + 22 files changed, 1611 insertions(+) create mode 100644 lib/librte_bitratestats/Makefile create mode 100644 lib/librte_bitratestats/rte_bitrate.c create mode 100644 lib/librte_bitratestats/rte_bitrate.h create mode 100644 lib/librte_bitratestats/rte_bitratestats_version.map create mode 100644 lib/librte_latencystats/Makefile create mode 100644 lib/librte_latencystats/rte_latencystats.c create mode 100644 lib/librte_latencystats/rte_latencystats.h create mode 100644 lib/librte_latencystats/rte_latencystats_version.map create mode 100644 lib/librte_metrics/Makefile create mode 100644 lib/librte_metrics/rte_metrics.c create mode 100644 lib/librte_metrics/rte_metrics.h create mode 100644 lib/librte_metrics/rte_metrics_version.map -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v5 1/4] lib: add information metrics library 2016-11-18 8:00 ` [dpdk-dev] [PATCH v5 0/4] Expanded statistics reporting Remy Horton @ 2016-11-18 8:00 ` Remy Horton 2016-11-18 8:00 ` [dpdk-dev] [PATCH v5 2/4] lib: add bitrate statistics library Remy Horton ` (3 subsequent siblings) 4 siblings, 0 replies; 115+ messages in thread From: Remy Horton @ 2016-11-18 8:00 UTC (permalink / raw) To: dev; +Cc: Thomas Monjalon This patch adds a new information metric library that allows other modules to register named metrics and update their values. It is intended to be independent of ethdev, rather than mixing ethdev and non-ethdev information in xstats. Signed-off-by: Remy Horton <remy.horton@intel.com> --- MAINTAINERS | 5 + config/common_base | 5 + doc/api/doxy-api-index.md | 1 + doc/api/doxy-api.conf | 1 + doc/guides/rel_notes/release_17_02.rst | 7 + lib/Makefile | 1 + lib/librte_metrics/Makefile | 51 +++++ lib/librte_metrics/rte_metrics.c | 308 +++++++++++++++++++++++++++++ lib/librte_metrics/rte_metrics.h | 190 ++++++++++++++++++ lib/librte_metrics/rte_metrics_version.map | 13 ++ mk/rte.app.mk | 2 + 11 files changed, 584 insertions(+) create mode 100644 lib/librte_metrics/Makefile create mode 100644 lib/librte_metrics/rte_metrics.c create mode 100644 lib/librte_metrics/rte_metrics.h create mode 100644 lib/librte_metrics/rte_metrics_version.map diff --git a/MAINTAINERS b/MAINTAINERS index d6bb8f8..52bd8a9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -595,6 +595,11 @@ F: lib/librte_jobstats/ F: examples/l2fwd-jobstats/ F: doc/guides/sample_app_ug/l2_forward_job_stats.rst +Metrics +M: Remy Horton <remy.horton@intel.com> +F: lib/librte_metrics/ +F: doc/guides/sample_app_ug/keep_alive.rst + Test Applications ----------------- diff --git a/config/common_base b/config/common_base index 4bff83a..dedc4c3 100644 --- a/config/common_base +++ b/config/common_base @@ -589,3 +589,8 @@ CONFIG_RTE_APP_TEST_RESOURCE_TAR=n CONFIG_RTE_TEST_PMD=y CONFIG_RTE_TEST_PMD_RECORD_CORE_CYCLES=n CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n + +# +# Compile the device metrics library +# +CONFIG_RTE_LIBRTE_METRICS=y diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md index 6675f96..ca50fa6 100644 --- a/doc/api/doxy-api-index.md +++ b/doc/api/doxy-api-index.md @@ -147,4 +147,5 @@ There are many libraries, so their headers may be grouped by topics: [common] (@ref rte_common.h), [ABI compat] (@ref rte_compat.h), [keepalive] (@ref rte_keepalive.h), + [Device Metrics] (@ref rte_metrics.h), [version] (@ref rte_version.h) diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf index 9dc7ae5..fe830eb 100644 --- a/doc/api/doxy-api.conf +++ b/doc/api/doxy-api.conf @@ -57,6 +57,7 @@ INPUT = doc/api/doxy-api-index.md \ lib/librte_reorder \ lib/librte_ring \ lib/librte_sched \ + lib/librte_metrics \ lib/librte_table \ lib/librte_timer \ lib/librte_vhost diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst index 3b65038..2d82dd1 100644 --- a/doc/guides/rel_notes/release_17_02.rst +++ b/doc/guides/rel_notes/release_17_02.rst @@ -34,6 +34,12 @@ New Features Refer to the previous release notes for examples. + * **Added information metric library.** + + A library that allows information metrics to be added and update. It is + intended to provide a reporting mechanism that is independent of the + ethdev library. + This section is a comment. do not overwrite or remove it. Also, make sure to start the actual text at the margin. ========================================================= @@ -152,6 +158,7 @@ The libraries prepended with a plus sign were incremented in this version. librte_mbuf.so.2 librte_mempool.so.2 librte_meter.so.1 + + librte_metrics.so.1 librte_net.so.1 librte_pdump.so.1 librte_pipeline.so.3 diff --git a/lib/Makefile b/lib/Makefile index 990f23a..5d85dcf 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -58,6 +58,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_TABLE) += librte_table DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += librte_pipeline DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump +DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni diff --git a/lib/librte_metrics/Makefile b/lib/librte_metrics/Makefile new file mode 100644 index 0000000..8d6e23a --- /dev/null +++ b/lib/librte_metrics/Makefile @@ -0,0 +1,51 @@ +# BSD LICENSE +# +# Copyright(c) 2016 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +include $(RTE_SDK)/mk/rte.vars.mk + +# library name +LIB = librte_metrics.a + +CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) + +EXPORT_MAP := rte_metrics_version.map + +LIBABIVER := 1 + +# all source are stored in SRCS-y +SRCS-$(CONFIG_RTE_LIBRTE_METRICS) := rte_metrics.c + +# Install header file +SYMLINK-$(CONFIG_RTE_LIBRTE_METRICS)-include += rte_metrics.h + +DEPDIRS-$(CONFIG_RTE_LIBRTE_METRICS) += lib/librte_eal + +include $(RTE_SDK)/mk/rte.lib.mk diff --git a/lib/librte_metrics/rte_metrics.c b/lib/librte_metrics/rte_metrics.c new file mode 100644 index 0000000..5edacc6 --- /dev/null +++ b/lib/librte_metrics/rte_metrics.c @@ -0,0 +1,308 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <string.h> +#include <sys/queue.h> + +#include <rte_common.h> +#include <rte_malloc.h> +#include <rte_metrics.h> +#include <rte_lcore.h> +#include <rte_memzone.h> +#include <rte_spinlock.h> + +#define RTE_METRICS_MAX_METRICS 256 +#define RTE_METRICS_MEMZONE_NAME "RTE_METRICS" + +/** + * Internal stats metadata and value entry. + * + * @internal + * @param name + * Name of metric + * @param value + * Current value for metric + * @param idx_next_set + * Index of next root element (zero for none) + * @param idx_next_metric + * Index of next metric in set (zero for none) + * + * Only the root of each set needs idx_next_set but since it has to be + * assumed that number of sets could equal total number of metrics, + * having a separate set metadata table doesn't save any memory. + */ +struct rte_metrics_meta_s { + char name[RTE_METRICS_MAX_NAME_LEN]; + uint64_t value[RTE_MAX_ETHPORTS]; + uint64_t nonport_value; + uint16_t idx_next_set; + uint16_t idx_next_stat; +}; + +/** + * Internal stats info structure. + * + * @internal + * @param idx_last_set + * Index of last metadata entry with valid data. This value is + * not valid if cnt_stats is zero. + * @param cnt_stats + * Number of metrics. + * @param metadata + * Stat data memory block. + * + * Offsets into metadata are used instead of pointers because ASLR + * means that having the same physical addresses in different + * processes is not guaranteed. + */ +struct rte_metrics_data_s { + uint16_t idx_last_set; + uint16_t cnt_stats; + struct rte_metrics_meta_s metadata[RTE_METRICS_MAX_METRICS]; + rte_spinlock_t lock; +}; + +void +rte_metrics_init(void) +{ + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + + if (rte_eal_process_type() != RTE_PROC_PRIMARY) + return; + + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); + if (memzone != NULL) + return; + memzone = rte_memzone_reserve(RTE_METRICS_MEMZONE_NAME, + sizeof(struct rte_metrics_data_s), rte_socket_id(), 0); + if (memzone == NULL) + rte_exit(EXIT_FAILURE, "Unable to allocate stats memzone\n"); + stats = memzone->addr; + memset(stats, 0, sizeof(struct rte_metrics_data_s)); + rte_spinlock_init(&stats->lock); +} + +int +rte_metrics_reg_metric(const char *name) +{ + const char *list_names[] = {name}; + + return rte_metrics_reg_metrics(list_names, 1); +} + +int +rte_metrics_reg_metrics(const char **names, uint16_t cnt_names) +{ + struct rte_metrics_meta_s *entry; + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + uint16_t idx_name; + uint16_t idx_base; + + /* Some sanity checks */ + if (cnt_names < 1 || names == NULL) + return -EINVAL; + + rte_metrics_init(); + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); + if (memzone == NULL) + return -EIO; + stats = memzone->addr; + + if (stats->cnt_stats + cnt_names >= RTE_METRICS_MAX_METRICS) + return -ENOMEM; + + rte_spinlock_lock(&stats->lock); + + /* Overwritten later if this is actually first set.. */ + stats->metadata[stats->idx_last_set].idx_next_set = stats->cnt_stats; + + stats->idx_last_set = idx_base = stats->cnt_stats; + + for (idx_name = 0; idx_name < cnt_names; idx_name++) { + entry = &stats->metadata[idx_name + stats->cnt_stats]; + strncpy(entry->name, names[idx_name], + RTE_METRICS_MAX_NAME_LEN); + memset(entry->value, 0, sizeof(entry->value)); + entry->idx_next_stat = idx_name + stats->cnt_stats + 1; + } + entry->idx_next_stat = 0; + entry->idx_next_set = 0; + stats->cnt_stats += cnt_names; + + rte_spinlock_unlock(&stats->lock); + + return idx_base; +} + +int +rte_metrics_update_metric(int port_id, uint16_t key, const uint64_t value) +{ + return rte_metrics_update_metrics(port_id, key, &value, 1); +} + +int +rte_metrics_update_metrics(int port_id, + uint16_t key, + const uint64_t *values, + uint32_t count) +{ + struct rte_metrics_meta_s *entry; + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + uint16_t idx_metric; + uint16_t idx_value; + uint16_t cnt_setsize; + + if (port_id != RTE_METRICS_NONPORT && + (port_id < 0 || port_id > RTE_MAX_ETHPORTS)) + return -EINVAL; + + rte_metrics_init(); + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); + if (memzone == NULL) + return -EIO; + stats = memzone->addr; + + rte_spinlock_lock(&stats->lock); + idx_metric = key; + cnt_setsize = 1; + while (idx_metric < stats->cnt_stats) { + entry = &stats->metadata[idx_metric]; + if (entry->idx_next_stat == 0) + break; + cnt_setsize++; + idx_metric++; + } + /* Check update does not cross set border */ + if (count > cnt_setsize) { + rte_spinlock_unlock(&stats->lock); + return -ERANGE; + } + + if (port_id == RTE_METRICS_NONPORT) + for (idx_value = 0; idx_value < count; idx_value++) { + idx_metric = key + idx_value; + stats->metadata[idx_metric].nonport_value = + values[idx_value]; + } + else + for (idx_value = 0; idx_value < count; idx_value++) { + idx_metric = key + idx_value; + stats->metadata[idx_metric].value[port_id] = + values[idx_value]; + } + rte_spinlock_unlock(&stats->lock); + return 0; +} + +int +rte_metrics_get_names(struct rte_metric_name *names, + uint16_t capacity) +{ + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + uint16_t idx_name; + int return_value; + + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); + /* If not allocated, fail silently */ + if (memzone == NULL) + return 0; + + stats = memzone->addr; + rte_spinlock_lock(&stats->lock); + if (names != NULL) { + if (capacity < stats->cnt_stats) { + rte_spinlock_unlock(&stats->lock); + return -ERANGE; + } + for (idx_name = 0; idx_name < stats->cnt_stats; idx_name++) + strncpy(names[idx_name].name, + stats->metadata[idx_name].name, + RTE_METRICS_MAX_NAME_LEN); + } + return_value = stats->cnt_stats; + rte_spinlock_unlock(&stats->lock); + return return_value; +} + +int +rte_metrics_get_values(int port_id, + struct rte_metric_value *values, + uint16_t capacity) +{ + struct rte_metrics_meta_s *entry; + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + uint16_t idx_name; + int return_value; + + if (port_id != RTE_METRICS_NONPORT && + (port_id < 0 || port_id > RTE_MAX_ETHPORTS)) + return -EINVAL; + + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); + /* If not allocated, fail silently */ + if (memzone == NULL) + return 0; + stats = memzone->addr; + rte_spinlock_lock(&stats->lock); + + if (values != NULL) { + if (capacity < stats->cnt_stats) { + rte_spinlock_unlock(&stats->lock); + return -ERANGE; + } + if (port_id == RTE_METRICS_NONPORT) + for (idx_name = 0; + idx_name < stats->cnt_stats; + idx_name++) { + entry = &stats->metadata[idx_name]; + values[idx_name].key = idx_name; + values[idx_name].value = entry->nonport_value; + } + else + for (idx_name = 0; + idx_name < stats->cnt_stats; + idx_name++) { + entry = &stats->metadata[idx_name]; + values[idx_name].key = idx_name; + values[idx_name].value = entry->value[port_id]; + } + } + return_value = stats->cnt_stats; + rte_spinlock_unlock(&stats->lock); + return return_value; +} diff --git a/lib/librte_metrics/rte_metrics.h b/lib/librte_metrics/rte_metrics.h new file mode 100644 index 0000000..c58b366 --- /dev/null +++ b/lib/librte_metrics/rte_metrics.h @@ -0,0 +1,190 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * + * RTE Metrics module + * + * Metric information is populated using a push model, where the + * information provider calls an update function on the relevant + * metrics. Currently only bulk querying of metrics is supported. + */ + +#ifndef _RTE_METRICS_H_ +#define _RTE_METRICS_H_ + +/** Maximum length of metric name (including null-terminator) */ +#define RTE_METRICS_MAX_NAME_LEN 64 + +/** Used to indicate port-independent information */ +#define RTE_METRICS_NONPORT -1 + + +/** + * Metric name + */ +struct rte_metric_name { + /** String describing metric */ + char name[RTE_METRICS_MAX_NAME_LEN]; +}; + + +/** + * Metric name. + */ +struct rte_metric_value { + /** Numeric identifier of metric */ + uint16_t key; + /** Value for metric */ + uint64_t value; +}; + + +/** + * Initializes metric module. This only has to be explicitly called if you + * intend to use rte_metrics_reg_metric() or rte_metrics_reg_metrics() from a + * secondary process. This function must be called from a primary process. + */ +void rte_metrics_init(void); + + +/** + * Register a metric + * + * @param name + * Metric name + * + * @return + * - Zero or positive: Success + * - Negative: Failure + */ +int rte_metrics_reg_metric(const char *name); + +/** + * Register a set of metrics + * + * @param names + * List of metric names + * + * @param cnt_names + * Number of metrics in set + * + * @return + * - Zero or positive: Success + * - Negative: Failure + */ +int rte_metrics_reg_metrics(const char **names, uint16_t cnt_names); + +/** + * Get metric name-key lookup table. + * + * @param names + * Array of names to receive key names + * + * @param capacity + * Space available in names + * + * @return + * - Non-negative: Success (number of names) + * - Negative: Failure + */ +int rte_metrics_get_names( + struct rte_metric_name *names, + uint16_t capacity); + +/** + * Fetch metrics. + * + * @param port_id + * Port id to query + * + * @param values + * Array to receive values and their keys + * + * @param capacity + * Space available in values + * + * @return + * - Non-negative: Success (number of names) + * - Negative: Failure + */ +int rte_metrics_get_values( + int port_id, + struct rte_metric_value *values, + uint16_t capacity); + +/** + * Updates a metric + * + * @param port_id + * Port to update metrics for + * @param key + * Id of metric to update + * @param value + * New value + * + * @return + * - -EIO if unable to access shared metrics memory + * - Zero on success + */ +int rte_metrics_update_metric( + int port_id, + uint16_t key, + const uint64_t value); + +/** + * Updates a metric set. Note that it is an error to try to + * update across a set boundary. + * + * @param port_id + * Port to update metrics for + * @param key + * Base id of metrics set to update + * @param values + * Set of new values + * @param count + * Number of new values + * + * @return + * - -ERANGE if count exceeds metric set size + * - -EIO if upable to access shared metrics memory + * - Zero on success + */ +int rte_metrics_update_metrics( + int port_id, + uint16_t key, + const uint64_t *values, + uint32_t count); + +#endif diff --git a/lib/librte_metrics/rte_metrics_version.map b/lib/librte_metrics/rte_metrics_version.map new file mode 100644 index 0000000..f904814 --- /dev/null +++ b/lib/librte_metrics/rte_metrics_version.map @@ -0,0 +1,13 @@ +DPDK_17.02 { + global: + + rte_metrics_get_names; + rte_metrics_get_values; + rte_metrics_init; + rte_metrics_reg_metric; + rte_metrics_reg_metrics; + rte_metrics_update_metric; + rte_metrics_update_metrics; + + local: *; +}; diff --git a/mk/rte.app.mk b/mk/rte.app.mk index f75f0e2..40fcf33 100644 --- a/mk/rte.app.mk +++ b/mk/rte.app.mk @@ -98,6 +98,8 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_RING) += -lrte_ring _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL) += -lrte_eal _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE) += -lrte_cmdline _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE) += -lrte_cfgfile +_LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS) += -lrte_metrics + _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += -lrte_pmd_bond _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += -lrte_pmd_xenvirt -lxenstore -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v5 2/4] lib: add bitrate statistics library 2016-11-18 8:00 ` [dpdk-dev] [PATCH v5 0/4] Expanded statistics reporting Remy Horton 2016-11-18 8:00 ` [dpdk-dev] [PATCH v5 1/4] lib: add information metrics library Remy Horton @ 2016-11-18 8:00 ` Remy Horton 2016-11-18 8:00 ` [dpdk-dev] [PATCH v5 3/4] app/test-pmd: add support for bitrate statistics Remy Horton ` (2 subsequent siblings) 4 siblings, 0 replies; 115+ messages in thread From: Remy Horton @ 2016-11-18 8:00 UTC (permalink / raw) To: dev; +Cc: Thomas Monjalon This patch adds a library that calculates peak and average data-rate statistics. For ethernet devices. These statistics are reported using the metrics library. Signed-off-by: Remy Horton <remy.horton@intel.com> --- MAINTAINERS | 4 + config/common_base | 5 + doc/api/doxy-api-index.md | 1 + doc/api/doxy-api.conf | 1 + doc/guides/rel_notes/release_17_02.rst | 6 + lib/Makefile | 1 + lib/librte_bitratestats/Makefile | 53 +++++++++ lib/librte_bitratestats/rte_bitrate.c | 128 +++++++++++++++++++++ lib/librte_bitratestats/rte_bitrate.h | 80 +++++++++++++ .../rte_bitratestats_version.map | 9 ++ mk/rte.app.mk | 1 + 11 files changed, 289 insertions(+) create mode 100644 lib/librte_bitratestats/Makefile create mode 100644 lib/librte_bitratestats/rte_bitrate.c create mode 100644 lib/librte_bitratestats/rte_bitrate.h create mode 100644 lib/librte_bitratestats/rte_bitratestats_version.map diff --git a/MAINTAINERS b/MAINTAINERS index 52bd8a9..d6bbdd5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -600,6 +600,10 @@ M: Remy Horton <remy.horton@intel.com> F: lib/librte_metrics/ F: doc/guides/sample_app_ug/keep_alive.rst +Bit-rate statistica +M: Remy Horton <remy.horton@intel.com> +F: lib/librte_bitratestats/ + Test Applications ----------------- diff --git a/config/common_base b/config/common_base index dedc4c3..beca7ec 100644 --- a/config/common_base +++ b/config/common_base @@ -594,3 +594,8 @@ CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n # Compile the device metrics library # CONFIG_RTE_LIBRTE_METRICS=y + +# +# Compile the bitrate statistics library +# +CONFIG_RTE_LIBRTE_BITRATE=y diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md index ca50fa6..91e8ea6 100644 --- a/doc/api/doxy-api-index.md +++ b/doc/api/doxy-api-index.md @@ -148,4 +148,5 @@ There are many libraries, so their headers may be grouped by topics: [ABI compat] (@ref rte_compat.h), [keepalive] (@ref rte_keepalive.h), [Device Metrics] (@ref rte_metrics.h), + [Bitrate Statistics] (@ref rte_bitrate.h), [version] (@ref rte_version.h) diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf index fe830eb..8765ddd 100644 --- a/doc/api/doxy-api.conf +++ b/doc/api/doxy-api.conf @@ -58,6 +58,7 @@ INPUT = doc/api/doxy-api-index.md \ lib/librte_ring \ lib/librte_sched \ lib/librte_metrics \ + lib/librte_bitratestats \ lib/librte_table \ lib/librte_timer \ lib/librte_vhost diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst index 2d82dd1..0f7c06d 100644 --- a/doc/guides/rel_notes/release_17_02.rst +++ b/doc/guides/rel_notes/release_17_02.rst @@ -40,6 +40,11 @@ New Features intended to provide a reporting mechanism that is independent of the ethdev library. + * **Added bit-rate calculation library.** + + A library that can be used to calculate device bit-rates. Calculated + bitrates are reported using the metrics library. + This section is a comment. do not overwrite or remove it. Also, make sure to start the actual text at the margin. ========================================================= @@ -143,6 +148,7 @@ The libraries prepended with a plus sign were incremented in this version. .. code-block:: diff librte_acl.so.2 + + librte_bitratestats.so.1 librte_cfgfile.so.2 librte_cmdline.so.2 librte_cryptodev.so.2 diff --git a/lib/Makefile b/lib/Makefile index 5d85dcf..e211bc0 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -59,6 +59,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += librte_pipeline DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics +DIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += librte_bitratestats ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni diff --git a/lib/librte_bitratestats/Makefile b/lib/librte_bitratestats/Makefile new file mode 100644 index 0000000..b725d4e --- /dev/null +++ b/lib/librte_bitratestats/Makefile @@ -0,0 +1,53 @@ +# BSD LICENSE +# +# Copyright(c) 2016 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +include $(RTE_SDK)/mk/rte.vars.mk + +# library name +LIB = librte_bitratestats.a + +CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) + +EXPORT_MAP := rte_bitratestats_version.map + +LIBABIVER := 1 + +# all source are stored in SRCS-y +SRCS-$(CONFIG_RTE_LIBRTE_BITRATE) := rte_bitrate.c + +# Install header file +SYMLINK-$(CONFIG_RTE_LIBRTE_BITRATE)-include += rte_bitrate.h + +DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_eal +DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_ether +DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_metrics + +include $(RTE_SDK)/mk/rte.lib.mk diff --git a/lib/librte_bitratestats/rte_bitrate.c b/lib/librte_bitratestats/rte_bitrate.c new file mode 100644 index 0000000..6346bb1 --- /dev/null +++ b/lib/librte_bitratestats/rte_bitrate.c @@ -0,0 +1,128 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <rte_common.h> +#include <rte_ethdev.h> +#include <rte_malloc.h> +#include <rte_metrics.h> +#include <rte_bitrate.h> + +/* + * Persistent bit-rate data. + * @internal + */ +struct rte_stats_bitrate_s { + uint64_t last_ibytes; + uint64_t last_obytes; + uint64_t peak_ibits; + uint64_t peak_obits; + uint64_t ewma_ibits; + uint64_t ewma_obits; +}; + +struct rte_stats_bitrates_s { + struct rte_stats_bitrate_s port_stats[RTE_MAX_ETHPORTS]; + uint16_t id_stats_set; +}; + +struct rte_stats_bitrates_s * +rte_stats_bitrate_create(void) +{ + return rte_zmalloc(NULL, sizeof(struct rte_stats_bitrates_s), 0); +} + +int +rte_stats_bitrate_reg(struct rte_stats_bitrates_s *bitrate_data) +{ + const char *names[] = { + "mean_bits_in", "mean_bits_out", + "peak_bits_in", "peak_bits_out", + }; + int return_value; + + return_value = rte_metrics_reg_metrics(&names[0], 4); + if (return_value >= 0) + bitrate_data->id_stats_set = return_value; + return return_value; +} + +int +rte_stats_bitrate_calc(struct rte_stats_bitrates_s *bitrate_data, + uint8_t port_id) +{ + struct rte_stats_bitrate_s *port_data; + struct rte_eth_stats eth_stats; + int ret_code; + uint64_t cnt_bits; + int64_t delta; + const int64_t alpha_percent = 20; + uint64_t values[4]; + + ret_code = rte_eth_stats_get(port_id, ð_stats); + if (ret_code != 0) + return ret_code; + + port_data = &bitrate_data->port_stats[port_id]; + + /* Incoming bitrate. This is an iteratively calculated EWMA + * (Expomentially Weighted Moving Average) that uses a + * weighting factor of alpha_percent. + */ + cnt_bits = (eth_stats.ibytes - port_data->last_ibytes) << 3; + port_data->last_ibytes = eth_stats.ibytes; + if (cnt_bits > port_data->peak_ibits) + port_data->peak_ibits = cnt_bits; + delta = cnt_bits; + delta -= port_data->ewma_ibits; + /* The +50 fixes integer rounding during divison */ + delta = (delta * alpha_percent + 50) / 100; + port_data->ewma_ibits += delta; + + /* Outgoing bitrate (also EWMA) */ + cnt_bits = (eth_stats.obytes - port_data->last_obytes) << 3; + port_data->last_obytes = eth_stats.obytes; + if (cnt_bits > port_data->peak_obits) + port_data->peak_obits = cnt_bits; + delta = cnt_bits; + delta -= port_data->ewma_obits; + delta = (delta * alpha_percent + 50) / 100; + port_data->ewma_obits += delta; + + values[0] = port_data->ewma_ibits; + values[1] = port_data->ewma_obits; + values[2] = port_data->peak_ibits; + values[3] = port_data->peak_obits; + rte_metrics_update_metrics(port_id, bitrate_data->id_stats_set, + values, 4); + return 0; +} diff --git a/lib/librte_bitratestats/rte_bitrate.h b/lib/librte_bitratestats/rte_bitrate.h new file mode 100644 index 0000000..bc87c5e --- /dev/null +++ b/lib/librte_bitratestats/rte_bitrate.h @@ -0,0 +1,80 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +/** + * Bitrate statistics data structure. + * This data structure is intentionally opaque. + */ +struct rte_stats_bitrates_s; + + +/** + * Allocate a bitrate statistics structure + * + * @return + * - Pointer to structure on success + * - NULL on error (zmalloc failure) + */ +struct rte_stats_bitrates_s *rte_stats_bitrate_create(void); + + +/** + * Register bitrate statistics with the metric library. + * + * @param bitrate_data + * Pointer allocated by rte_stats_create() + * + * @return + * Zero on success + * Negative on error + */ +int rte_stats_bitrate_reg(struct rte_stats_bitrates_s *bitrate_data); + + +/** + * Calculate statistics for current time window. The period with which + * this function is called should be the intended sampling window width. + * + * @param bitrate_data + * Bitrate statistics data pointer + * + * @param port_id + * Port id to calculate statistics for + * + * @return + * - Zero on success + * - Negative value on error + */ +int rte_stats_bitrate_calc(struct rte_stats_bitrates_s *bitrate_data, + uint8_t port_id); diff --git a/lib/librte_bitratestats/rte_bitratestats_version.map b/lib/librte_bitratestats/rte_bitratestats_version.map new file mode 100644 index 0000000..66f232f --- /dev/null +++ b/lib/librte_bitratestats/rte_bitratestats_version.map @@ -0,0 +1,9 @@ +DPDK_17.02 { + global: + + rte_stats_bitrate_calc; + rte_stats_bitrate_create; + rte_stats_bitrate_reg; + + local: *; +}; diff --git a/mk/rte.app.mk b/mk/rte.app.mk index 40fcf33..6aac5ac 100644 --- a/mk/rte.app.mk +++ b/mk/rte.app.mk @@ -99,6 +99,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL) += -lrte_eal _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE) += -lrte_cmdline _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE) += -lrte_cfgfile _LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS) += -lrte_metrics +_LDLIBS-$(CONFIG_RTE_LIBRTE_BITRATE) += -lrte_bitratestats _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += -lrte_pmd_bond -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v5 3/4] app/test-pmd: add support for bitrate statistics 2016-11-18 8:00 ` [dpdk-dev] [PATCH v5 0/4] Expanded statistics reporting Remy Horton 2016-11-18 8:00 ` [dpdk-dev] [PATCH v5 1/4] lib: add information metrics library Remy Horton 2016-11-18 8:00 ` [dpdk-dev] [PATCH v5 2/4] lib: add bitrate statistics library Remy Horton @ 2016-11-18 8:00 ` Remy Horton 2016-11-18 8:00 ` [dpdk-dev] [PATCH v5 4/4] latencystats: added new library for latency stats Remy Horton 2017-01-11 16:03 ` [dpdk-dev] [PATCH v6 0/4] Expanded statistics reporting Remy Horton 4 siblings, 0 replies; 115+ messages in thread From: Remy Horton @ 2016-11-18 8:00 UTC (permalink / raw) To: dev; +Cc: Thomas Monjalon Signed-off-by: Remy Horton <remy.horton@intel.com> --- app/test-pmd/testpmd.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c index a0332c2..60c635f 100644 --- a/app/test-pmd/testpmd.c +++ b/app/test-pmd/testpmd.c @@ -78,6 +78,10 @@ #ifdef RTE_LIBRTE_PDUMP #include <rte_pdump.h> #endif +#include <rte_metrics.h> +#ifdef RTE_LIBRTE_BITRATE +#include <rte_bitrate.h> +#endif #include "testpmd.h" @@ -322,6 +326,9 @@ uint16_t nb_rx_queue_stats_mappings = 0; unsigned max_socket = 0; +/* Bitrate statistics */ +struct rte_stats_bitrates_s *bitrate_data; + /* Forward function declarations */ static void map_port_queue_stats_mapping_registers(uint8_t pi, struct rte_port *port); static void check_all_ports_link_status(uint32_t port_mask); @@ -921,12 +928,32 @@ run_pkt_fwd_on_lcore(struct fwd_lcore *fc, packet_fwd_t pkt_fwd) struct fwd_stream **fsm; streamid_t nb_fs; streamid_t sm_id; +#ifdef RTE_LIBRTE_BITRATE + uint64_t tics_per_1sec; + uint64_t tics_datum; + uint64_t tics_current; + uint8_t idx_port, cnt_ports; +#endif +#ifdef RTE_LIBRTE_BITRATE + cnt_ports = rte_eth_dev_count(); + tics_datum = rte_rdtsc(); + tics_per_1sec = rte_get_timer_hz(); +#endif fsm = &fwd_streams[fc->stream_idx]; nb_fs = fc->stream_nb; do { for (sm_id = 0; sm_id < nb_fs; sm_id++) (*pkt_fwd)(fsm[sm_id]); +#ifdef RTE_LIBRTE_BITRATE + tics_current = rte_rdtsc(); + if (tics_current - tics_datum >= tics_per_1sec) { + /* Periodic bitrate calculation */ + for (idx_port = 0; idx_port < cnt_ports; idx_port++) + rte_stats_bitrate_calc(bitrate_data, idx_port); + tics_datum = tics_current; + } +#endif } while (! fc->stopped); } @@ -2133,6 +2160,15 @@ main(int argc, char** argv) FOREACH_PORT(port_id, ports) rte_eth_promiscuous_enable(port_id); + /* Setup bitrate stats */ +#ifdef RTE_LIBRTE_BITRATE + bitrate_data = rte_stats_bitrate_create(); + if (bitrate_data == NULL) + rte_exit(EXIT_FAILURE, "Could not allocate bitrate data.\n"); + rte_stats_bitrate_reg(bitrate_data); +#endif + + #ifdef RTE_LIBRTE_CMDLINE if (interactive == 1) { if (auto_start) { -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v5 4/4] latencystats: added new library for latency stats 2016-11-18 8:00 ` [dpdk-dev] [PATCH v5 0/4] Expanded statistics reporting Remy Horton ` (2 preceding siblings ...) 2016-11-18 8:00 ` [dpdk-dev] [PATCH v5 3/4] app/test-pmd: add support for bitrate statistics Remy Horton @ 2016-11-18 8:00 ` Remy Horton 2017-01-11 16:03 ` [dpdk-dev] [PATCH v6 0/4] Expanded statistics reporting Remy Horton 4 siblings, 0 replies; 115+ messages in thread From: Remy Horton @ 2016-11-18 8:00 UTC (permalink / raw) To: dev; +Cc: Thomas Monjalon, Reshma Pattan Add a library designed to calculate latency statistics and report them to the application when queried. The library measures minimum, average and maximum latencies, and jitter in nano seconds. The current implementation supports global latency stats, i.e. per application stats. Added new field to mbuf struct to mark the packet arrival time on Rx. Modify testpmd code to initialize/uninitialize latency statistics calulation. Modify the dpdk-procinfo process to display the newly added metrics. Added new command line option "--metrics" to display metrics. APIs: * Added APIs to initialize and un initialize latency stats calculation. * Added API to retrieve latency stats names and values. Functionality: * The library will register ethdev Rx/Tx callbacks for each active port, queue combinations. * The library will register latency stats names with new metrics library. * Rx packets will be marked with time stamp on each sampling interval. * On Tx side, packets with time stamp will be considered for calculating the minimum, maximum, average latencies and also jitter. * Average latency is calculated using exponential weighted moving average method. * Minimum and maximum latencies will be low and high latency values observed so far. * Jitter calculation is done based on inter packet delay variation. * Measured stats are reported to the metrics library in a separate pthread. * Measured stats can be retrieved via get API of the libray (or) by calling generic get API of the new metrics library. Signed-off-by: Reshma Pattan <reshma.pattan@intel.com> Signed-off-by: Remy Horton <remy.horton@intel.com> --- MAINTAINERS | 4 + app/proc_info/main.c | 70 ++++ app/test-pmd/testpmd.c | 10 + config/common_base | 5 + doc/api/doxy-api-index.md | 1 + doc/api/doxy-api.conf | 1 + doc/guides/rel_notes/release_17_02.rst | 5 + lib/Makefile | 1 + lib/librte_latencystats/Makefile | 57 +++ lib/librte_latencystats/rte_latencystats.c | 389 +++++++++++++++++++++ lib/librte_latencystats/rte_latencystats.h | 146 ++++++++ .../rte_latencystats_version.map | 10 + lib/librte_mbuf/rte_mbuf.h | 3 + mk/rte.app.mk | 2 +- 14 files changed, 703 insertions(+), 1 deletion(-) create mode 100644 lib/librte_latencystats/Makefile create mode 100644 lib/librte_latencystats/rte_latencystats.c create mode 100644 lib/librte_latencystats/rte_latencystats.h create mode 100644 lib/librte_latencystats/rte_latencystats_version.map diff --git a/MAINTAINERS b/MAINTAINERS index d6bbdd5..da7f9d1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -713,3 +713,7 @@ F: examples/tep_termination/ F: examples/vmdq/ F: examples/vmdq_dcb/ F: doc/guides/sample_app_ug/vmdq_dcb_forwarding.rst + +Latency Stats +M: Reshma Pattan <reshma.pattan@intel.com> +F: lib/librte_latencystats/ diff --git a/app/proc_info/main.c b/app/proc_info/main.c index 2c56d10..33a4b39 100644 --- a/app/proc_info/main.c +++ b/app/proc_info/main.c @@ -57,6 +57,7 @@ #include <rte_atomic.h> #include <rte_branch_prediction.h> #include <rte_string_fns.h> +#include <rte_metrics.h> /* Maximum long option length for option parsing. */ #define MAX_LONG_OPT_SZ 64 @@ -68,6 +69,8 @@ static uint32_t enabled_port_mask; static uint32_t enable_stats; /**< Enable xstats. */ static uint32_t enable_xstats; +/**< Enable metrics. */ +static uint32_t enable_metrics; /**< Enable stats reset. */ static uint32_t reset_stats; /**< Enable xstats reset. */ @@ -85,6 +88,8 @@ proc_info_usage(const char *prgname) " --stats: to display port statistics, enabled by default\n" " --xstats: to display extended port statistics, disabled by " "default\n" + " --metrics: to display derived metrics of the ports, disabled by " + "default\n" " --stats-reset: to reset port statistics\n" " --xstats-reset: to reset port extended statistics\n", prgname); @@ -127,6 +132,7 @@ proc_info_parse_args(int argc, char **argv) {"stats", 0, NULL, 0}, {"stats-reset", 0, NULL, 0}, {"xstats", 0, NULL, 0}, + {"metrics", 0, NULL, 0}, {"xstats-reset", 0, NULL, 0}, {NULL, 0, 0, 0} }; @@ -159,6 +165,10 @@ proc_info_parse_args(int argc, char **argv) else if (!strncmp(long_option[option_index].name, "xstats", MAX_LONG_OPT_SZ)) enable_xstats = 1; + else if (!strncmp(long_option[option_index].name, + "metrics", + MAX_LONG_OPT_SZ)) + enable_metrics = 1; /* Reset stats */ if (!strncmp(long_option[option_index].name, "stats-reset", MAX_LONG_OPT_SZ)) @@ -301,6 +311,60 @@ nic_xstats_clear(uint8_t port_id) printf("\n NIC extended statistics for port %d cleared\n", port_id); } +static void +metrics_display(int port_id) +{ + struct rte_metric_value *metrics; + struct rte_metric_name *names; + int len, ret; + static const char *nic_stats_border = "########################"; + + memset(&metrics, 0, sizeof(struct rte_metric_value)); + len = rte_metrics_get_names(NULL, 0); + if (len < 0) { + printf("Cannot get metrics count\n"); + return; + } + + metrics = malloc(sizeof(struct rte_metric_value) * len); + if (metrics == NULL) { + printf("Cannot allocate memory for metrics\n"); + return; + } + + names = malloc(sizeof(struct rte_metric_name) * len); + if (names == NULL) { + printf("Cannot allocate memory for metrcis names\n"); + free(metrics); + return; + } + + if (len != rte_metrics_get_names(names, len)) { + printf("Cannot get metrics names\n"); + free(metrics); + free(names); + return; + } + + printf("###### metrics for port %-2d #########\n", port_id); + printf("%s############################\n", nic_stats_border); + ret = rte_metrics_get_values(port_id, metrics, len); + if (ret < 0 || ret > len) { + printf("Cannot get metrics values\n"); + free(metrics); + free(names); + return; + } + + int i; + for (i = 0; i < len; i++) + printf("%s: %"PRIu64"\n", names[i].name, metrics[i].value); + + printf("%s############################\n", nic_stats_border); + free(metrics); + free(names); +} + int main(int argc, char **argv) { @@ -360,8 +424,14 @@ main(int argc, char **argv) nic_stats_clear(i); else if (reset_xstats) nic_xstats_clear(i); + else if (enable_metrics) + metrics_display(i); } } + /* print port independent stats */ + if (enable_metrics) + metrics_display(RTE_METRICS_NONPORT); + return 0; } diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c index 60c635f..774aa54 100644 --- a/app/test-pmd/testpmd.c +++ b/app/test-pmd/testpmd.c @@ -82,6 +82,10 @@ #ifdef RTE_LIBRTE_BITRATE #include <rte_bitrate.h> #endif +#include <rte_metrics.h> +#ifdef RTE_LIBRTE_LATENCY_STATS +#include <rte_latencystats.h> +#endif #include "testpmd.h" @@ -2102,6 +2106,9 @@ signal_handler(int signum) /* uninitialize packet capture framework */ rte_pdump_uninit(); #endif +#ifdef RTE_LIBRTE_LATENCY_STATS + rte_latencystats_uninit(); +#endif force_quit(); /* exit with the expected status */ signal(signum, SIG_DFL); @@ -2159,6 +2166,9 @@ main(int argc, char** argv) /* set all ports to promiscuous mode by default */ FOREACH_PORT(port_id, ports) rte_eth_promiscuous_enable(port_id); +#ifdef RTE_LIBRTE_LATENCY_STATS + rte_latencystats_init(1, NULL); +#endif /* Setup bitrate stats */ #ifdef RTE_LIBRTE_BITRATE diff --git a/config/common_base b/config/common_base index beca7ec..61d9352 100644 --- a/config/common_base +++ b/config/common_base @@ -599,3 +599,8 @@ CONFIG_RTE_LIBRTE_METRICS=y # Compile the bitrate statistics library # CONFIG_RTE_LIBRTE_BITRATE=y + +# +# Compile the latency statistics library +# +CONFIG_RTE_LIBRTE_LATENCY_STATS=y diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md index 91e8ea6..b98e5b5 100644 --- a/doc/api/doxy-api-index.md +++ b/doc/api/doxy-api-index.md @@ -149,4 +149,5 @@ There are many libraries, so their headers may be grouped by topics: [keepalive] (@ref rte_keepalive.h), [Device Metrics] (@ref rte_metrics.h), [Bitrate Statistics] (@ref rte_bitrate.h), + [Latency stats] (@ref rte_latencystats.h), [version] (@ref rte_version.h) diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf index 8765ddd..40295ac 100644 --- a/doc/api/doxy-api.conf +++ b/doc/api/doxy-api.conf @@ -46,6 +46,7 @@ INPUT = doc/api/doxy-api-index.md \ lib/librte_jobstats \ lib/librte_kni \ lib/librte_kvargs \ + lib/librte_latencystats \ lib/librte_lpm \ lib/librte_mbuf \ lib/librte_mempool \ diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst index 0f7c06d..dbd0e2f 100644 --- a/doc/guides/rel_notes/release_17_02.rst +++ b/doc/guides/rel_notes/release_17_02.rst @@ -49,6 +49,10 @@ New Features Also, make sure to start the actual text at the margin. ========================================================= +* **Added latency stats library.** + A library that facilitates latency stats measurment of the dpdk based applications. + The library measures minimum, average, maximum latencies and also jitter + in nano seconds. Resolved Issues --------------- @@ -160,6 +164,7 @@ The libraries prepended with a plus sign were incremented in this version. librte_jobstats.so.1 librte_kni.so.2 librte_kvargs.so.1 + + librte_latencystats.so.1 librte_lpm.so.2 librte_mbuf.so.2 librte_mempool.so.2 diff --git a/lib/Makefile b/lib/Makefile index e211bc0..6fffa88 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -60,6 +60,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics DIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += librte_bitratestats +DIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += librte_latencystats ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni diff --git a/lib/librte_latencystats/Makefile b/lib/librte_latencystats/Makefile new file mode 100644 index 0000000..f744da6 --- /dev/null +++ b/lib/librte_latencystats/Makefile @@ -0,0 +1,57 @@ +# BSD LICENSE +# +# Copyright(c) 2016 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +include $(RTE_SDK)/mk/rte.vars.mk + +# library name +LIB = librte_latencystats.a + +CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3 +LDLIBS += -lm +LDLIBS += -lpthread + +EXPORT_MAP := rte_latencystats_version.map + +LIBABIVER := 1 + +# all source are stored in SRCS-y +SRCS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) := rte_latencystats.c + +# install this header file +SYMLINK-$(CONFIG_RTE_LIBRTE_LATENCY_STATS)-include := rte_latencystats.h + +# this lib depends upon: +DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_mbuf +DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_eal +DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_ether +DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_metrics + +include $(RTE_SDK)/mk/rte.lib.mk diff --git a/lib/librte_latencystats/rte_latencystats.c b/lib/librte_latencystats/rte_latencystats.c new file mode 100644 index 0000000..dcde7f6 --- /dev/null +++ b/lib/librte_latencystats/rte_latencystats.c @@ -0,0 +1,389 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <unistd.h> +#include <sys/types.h> +#include <stdbool.h> +#include <math.h> +#include <pthread.h> + +#include <rte_mbuf.h> +#include <rte_log.h> +#include <rte_cycles.h> +#include <rte_ethdev.h> +#include <rte_metrics.h> +#include <rte_memzone.h> +#include <rte_lcore.h> +#include <rte_timer.h> + +#include "rte_latencystats.h" + +/** Nano seconds per second */ +#define NS_PER_SEC 1E9 + +/** Clock cycles per nano second */ +#define CYCLES_PER_NS (rte_get_timer_hz() / NS_PER_SEC) + +/* Macros for printing using RTE_LOG */ +#define RTE_LOGTYPE_LATENCY_STATS RTE_LOGTYPE_USER1 + +static pthread_t latency_stats_thread; +static const char *MZ_RTE_LATENCY_STATS = "rte_latencystats"; +static int latency_stats_index; +static uint64_t samp_intvl; +static uint64_t timer_tsc; +static uint64_t prev_tsc; + +static struct rte_latency_stats { + float min_latency; /**< Minimum latency in nano seconds */ + float avg_latency; /**< Average latency in nano seconds */ + float max_latency; /**< Maximum latency in nano seconds */ + float jitter; /** Latency variation */ +} *glob_stats; + +static struct rxtx_cbs { + struct rte_eth_rxtx_callback *cb; +} rx_cbs[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT], + tx_cbs[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT]; + +struct latency_stats_nameoff { + char name[RTE_ETH_XSTATS_NAME_SIZE]; + unsigned int offset; +}; + +static const struct latency_stats_nameoff lat_stats_strings[] = { + {"min_latency_ns", offsetof(struct rte_latency_stats, min_latency)}, + {"avg_latency_ns", offsetof(struct rte_latency_stats, avg_latency)}, + {"max_latency_ns", offsetof(struct rte_latency_stats, max_latency)}, + {"jitter_ns", offsetof(struct rte_latency_stats, jitter)}, +}; + +#define NUM_LATENCY_STATS (sizeof(lat_stats_strings) / \ + sizeof(lat_stats_strings[0])) + +static __attribute__((noreturn)) void * +report_latency_stats(__rte_unused void *arg) +{ + for (;;) { + unsigned int i; + float *stats_ptr = NULL; + uint64_t values[NUM_LATENCY_STATS] = {0}; + int ret; + + for (i = 0; i < NUM_LATENCY_STATS; i++) { + stats_ptr = RTE_PTR_ADD(glob_stats, + lat_stats_strings[i].offset); + values[i] = (uint64_t)floor((*stats_ptr)/ + CYCLES_PER_NS); + } + + ret = rte_metrics_update_metrics(RTE_METRICS_NONPORT, + latency_stats_index, + values, NUM_LATENCY_STATS); + if (ret < 0) + RTE_LOG(INFO, LATENCY_STATS, + "Failed to push the stats\n"); + } +} + +static void +rte_latencystats_fill_values(struct rte_metric_value *values) +{ + unsigned int i; + float *stats_ptr = NULL; + + for (i = 0; i < NUM_LATENCY_STATS; i++) { + stats_ptr = RTE_PTR_ADD(glob_stats, + lat_stats_strings[i].offset); + values[i].key = i; + values[i].value = (uint64_t)floor((*stats_ptr)/ + CYCLES_PER_NS); + } +} + +static uint16_t +add_time_stamps(uint8_t pid __rte_unused, + uint16_t qid __rte_unused, + struct rte_mbuf **pkts, + uint16_t nb_pkts, + uint16_t max_pkts __rte_unused, + void *user_cb __rte_unused) +{ + unsigned int i; + uint64_t diff_tsc, now; + + /* + * For every sample interval, + * time stamp is marked on one received packet. + */ + now = rte_rdtsc(); + for (i = 0; i < nb_pkts; i++) { + diff_tsc = now - prev_tsc; + timer_tsc += diff_tsc; + if (timer_tsc >= samp_intvl) { + /* + * TBD: Mark the timestamp only + * if not already marked by the + * hardware or the PMD. + */ + pkts[i]->timestamp = now; + timer_tsc = 0; + } + prev_tsc = now; + now = rte_rdtsc(); + } + + return nb_pkts; +} + +static uint16_t +calc_latency(uint8_t pid __rte_unused, + uint16_t qid __rte_unused, + struct rte_mbuf **pkts, + uint16_t nb_pkts, + void *_ __rte_unused) +{ + unsigned int i, cnt = 0; + uint64_t now; + float latency[nb_pkts]; + static float prev_latency; + /* + * Alpha represents degree of weighting decrease in EWMA, + * a constant smoothing factor between 0 and 1. The value + * is used below for measuring average latency. + */ + const float alpha = 0.2; + + now = rte_rdtsc(); + for (i = 0; i < nb_pkts; i++) { + if (pkts[i]->timestamp) + latency[cnt++] = now - pkts[i]->timestamp; + } + + for (i = 0; i < cnt; i++) { + /* + * The jitter is calculated as statistical mean of interpacket + * delay variation. The "jitter estimate" is computed by taking + * the absolute values of the ipdv sequence and applying an + * exponential filter with parameter 1/16 to generate the + * estimate. i.e J=J+(|D(i-1,i)|-J)/16. Where J is jitter, + * D(i-1,i) is difference in latency of two consecutive packets + * i-1 and i. + * Reference: Calculated as per RFC 5481, sec 4.1, + * RFC 3393 sec 4.5, RFC 1889 sec. + */ + glob_stats->jitter += (abs(prev_latency - latency[i]) + - glob_stats->jitter)/16; + if (glob_stats->min_latency == 0) + glob_stats->min_latency = latency[i]; + else if (latency[i] < glob_stats->min_latency) + glob_stats->min_latency = latency[i]; + else if (latency[i] > glob_stats->max_latency) + glob_stats->max_latency = latency[i]; + /* + * The average latency is measured using exponential moving + * average, i.e. using EWMA + * https://en.wikipedia.org/wiki/Moving_average + */ + glob_stats->avg_latency += + alpha * (latency[i] - glob_stats->avg_latency); + prev_latency = latency[i]; + } + + return nb_pkts; +} + +int +rte_latencystats_init(uint64_t samp_intvl, + rte_latency_stats_flow_type_fn user_cb) +{ + unsigned int i; + uint8_t pid; + uint16_t qid; + struct rxtx_cbs *cbs = NULL; + const uint8_t nb_ports = rte_eth_dev_count(); + const char *ptr_strings[NUM_LATENCY_STATS] = {0}; + const struct rte_memzone *mz = NULL; + const unsigned int flags = 0; + + /** Allocate stats in shared memory fo muliti process support */ + mz = rte_memzone_reserve(MZ_RTE_LATENCY_STATS, sizeof(*glob_stats), + rte_socket_id(), flags); + if (mz == NULL) { + RTE_LOG(ERR, LATENCY_STATS, "Cannot reserve memory: %s:%d\n", + __func__, __LINE__); + return -ENOMEM; + } + + glob_stats = mz->addr; + samp_intvl *= CYCLES_PER_NS; + + /** Register latency stats with stats library */ + for (i = 0; i < NUM_LATENCY_STATS; i++) + ptr_strings[i] = lat_stats_strings[i].name; + + latency_stats_index = rte_metrics_reg_metrics(ptr_strings, + NUM_LATENCY_STATS); + if (latency_stats_index < 0) { + RTE_LOG(DEBUG, LATENCY_STATS, + "Failed to register latency stats names\n"); + return -1; + } + + /** Register Rx/Tx callbacks */ + for (pid = 0; pid < nb_ports; pid++) { + struct rte_eth_dev_info dev_info; + rte_eth_dev_info_get(pid, &dev_info); + for (qid = 0; qid < dev_info.nb_rx_queues; qid++) { + cbs = &rx_cbs[pid][qid]; + cbs->cb = rte_eth_add_first_rx_callback(pid, qid, + add_time_stamps, user_cb); + if (!cbs->cb) + RTE_LOG(INFO, LATENCY_STATS, "Failed to " + "register Rx callback for pid=%d, " + "qid=%d\n", pid, qid); + } + for (qid = 0; qid < dev_info.nb_tx_queues; qid++) { + cbs = &tx_cbs[pid][qid]; + cbs->cb = rte_eth_add_tx_callback(pid, qid, + calc_latency, user_cb); + if (!cbs->cb) + RTE_LOG(INFO, LATENCY_STATS, "Failed to " + "register Tx callback for pid=%d, " + "qid=%d\n", pid, qid); + } + } + + int ret = 0; + char thread_name[RTE_MAX_THREAD_NAME_LEN]; + + /** Create the host thread to update latency stats to stats library */ + ret = pthread_create(&latency_stats_thread, NULL, report_latency_stats, + NULL); + if (ret != 0) { + RTE_LOG(ERR, LATENCY_STATS, + "Failed to create the latency stats thread:%s, %s:%d\n", + strerror(errno), __func__, __LINE__); + return -1; + } + /** Set thread_name for aid in debugging */ + snprintf(thread_name, RTE_MAX_THREAD_NAME_LEN, "latency-stats-thread"); + ret = rte_thread_setname(latency_stats_thread, thread_name); + if (ret != 0) + RTE_LOG(DEBUG, LATENCY_STATS, + "Failed to set thread name for latency stats handling\n"); + + return 0; +} + +int +rte_latencystats_uninit(void) +{ + uint8_t pid; + uint16_t qid; + int ret = 0; + struct rxtx_cbs *cbs = NULL; + const uint8_t nb_ports = rte_eth_dev_count(); + + /** De register Rx/Tx callbacks */ + for (pid = 0; pid < nb_ports; pid++) { + struct rte_eth_dev_info dev_info; + rte_eth_dev_info_get(pid, &dev_info); + for (qid = 0; qid < dev_info.nb_rx_queues; qid++) { + cbs = &rx_cbs[pid][qid]; + ret = rte_eth_remove_rx_callback(pid, qid, cbs->cb); + if (ret) + RTE_LOG(INFO, LATENCY_STATS, "failed to " + "remove Rx callback for pid=%d, " + "qid=%d\n", pid, qid); + } + for (qid = 0; qid < dev_info.nb_tx_queues; qid++) { + cbs = &tx_cbs[pid][qid]; + ret = rte_eth_remove_tx_callback(pid, qid, cbs->cb); + if (ret) + RTE_LOG(INFO, LATENCY_STATS, "failed to " + "remove Tx callback for pid=%d, " + "qid=%d\n", pid, qid); + } + } + + /** Cancel the thread */ + ret = pthread_cancel(latency_stats_thread); + if (ret != 0) { + RTE_LOG(ERR, LATENCY_STATS, + "Failed to cancel latency stats update thread:" + "%s,%s:%d\n", + strerror(errno), __func__, __LINE__); + return -1; + } + + return 0; +} + +int +rte_latencystats_get_names(struct rte_metric_name *names, uint16_t size) +{ + unsigned int i; + + if (names == NULL || size < NUM_LATENCY_STATS) + return NUM_LATENCY_STATS; + + for (i = 0; i < NUM_LATENCY_STATS; i++) + snprintf(names[i].name, sizeof(names[i].name), + "%s", lat_stats_strings[i].name); + + return NUM_LATENCY_STATS; +} + +int +rte_latencystats_get(struct rte_metric_value *values, uint16_t size) +{ + if (size < NUM_LATENCY_STATS || values == NULL) + return NUM_LATENCY_STATS; + + if (rte_eal_process_type() == RTE_PROC_SECONDARY) { + const struct rte_memzone *mz; + mz = rte_memzone_lookup(MZ_RTE_LATENCY_STATS); + if (mz == NULL) { + RTE_LOG(ERR, LATENCY_STATS, + "Latency stats memzone not found\n"); + return -ENOMEM; + } + glob_stats = mz->addr; + } + + /* Retrieve latency stats */ + rte_latencystats_fill_values(values); + + return NUM_LATENCY_STATS; +} diff --git a/lib/librte_latencystats/rte_latencystats.h b/lib/librte_latencystats/rte_latencystats.h new file mode 100644 index 0000000..405b878 --- /dev/null +++ b/lib/librte_latencystats/rte_latencystats.h @@ -0,0 +1,146 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _RTE_LATENCYSTATS_H_ +#define _RTE_LATENCYSTATS_H_ + +/** + * @file + * RTE latency stats + * + * library to provide application and flow based latency stats. + */ + +#include <rte_metrics.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Note: This function pointer is for future flow based latency stats + * implementation. + * + * Function type used for identifting flow types of a Rx packet. + * + * The callback function is called on Rx for each packet. + * This function is used for flow based latency calculations. + * + * @param pkt + * Packet that has to be identified with its flow types. + * @param user_param + * The arbitrary user parameter passed in by the application when + * the callback was originally configured. + * @return + * The flow_mask, representing the multiple flow types of a packet. + */ +typedef uint16_t (*rte_latency_stats_flow_type_fn)(struct rte_mbuf *pkt, + void *user_param); + +/** + * Registers Rx/Tx callbacks for each active port, queue. + * + * @param samp_intvl + * Sampling time period in nano seconds, at which packet + * should be marked with time stamp. + * @param user_cb + * Note: This param is for future flow based latency stats + * implementation. + * User callback to be called to get flow types of a packet. + * Used for flow based latency calculation. + * If the value is NULL, global stats will be calculated, + * else flow based latency stats will be calculated. + * For now just pass on the NULL value to this param. + * @return + * -1 : On error + * -ENOMEM: On error + * 0 : On success + */ +int rte_latencystats_init(uint64_t samp_intvl, + rte_latency_stats_flow_type_fn user_cb); + +/** + * Removes registered Rx/Tx callbacks for each active port, queue. + * + * @return + * -1: On error + * 0: On success + */ +int rte_latencystats_uninit(void); + +/** + * Retrieve names of latency statistics + * + * @param names + * Block of memory to insert names into. Must be at least size in capacity. + * If set to NULL, function returns required capacity. + * @param size + * Capacity of latency stats names (number of names). + * @return + * - positive value lower or equal to size: success. The return value + * is the number of entries filled in the stats table. + * - positive value higher than size: error, the given statistics table + * is too small. The return value corresponds to the size that should + * be given to succeed. The entries in the table are not valid and + * shall not be used by the caller. + */ +int rte_latencystats_get_names(struct rte_metric_name *names, + uint16_t size); + +/** + * Retrieve latency statistics. + * + * @param values + * A pointer to a table of structure of type *rte_metric_value* + * to be filled with latency statistics ids and values. + * This parameter can be set to NULL if size is 0. + * @param size + * The size of the stats table, which should be large enough to store + * all the latency stats. + * @return + * - positive value lower or equal to size: success. The return value + * is the number of entries filled in the stats table. + * - positive value higher than size: error, the given statistics table + * is too small. The return value corresponds to the size that should + * be given to succeed. The entries in the table are not valid and + * shall not be used by the caller. + * -ENOMEM: On failure. + */ +int rte_latencystats_get(struct rte_metric_value *values, + uint16_t size); + +#ifdef __cplusplus +} +#endif + +#endif /* _RTE_LATENCYSTATS_H_ */ diff --git a/lib/librte_latencystats/rte_latencystats_version.map b/lib/librte_latencystats/rte_latencystats_version.map new file mode 100644 index 0000000..502018e --- /dev/null +++ b/lib/librte_latencystats/rte_latencystats_version.map @@ -0,0 +1,10 @@ +DPDK_17.02 { + global: + + rte_latencystats_get; + rte_latencystats_get_names; + rte_latencystats_init; + rte_latencystats_uninit; + + local: *; +}; diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h index ead7c6e..44ba922 100644 --- a/lib/librte_mbuf/rte_mbuf.h +++ b/lib/librte_mbuf/rte_mbuf.h @@ -493,6 +493,9 @@ struct rte_mbuf { /** Timesync flags for use with IEEE1588. */ uint16_t timesync; + + /** Timestamp for measuring latency. */ + uint64_t timestamp; } __rte_cache_aligned; /** diff --git a/mk/rte.app.mk b/mk/rte.app.mk index 6aac5ac..1d36fad 100644 --- a/mk/rte.app.mk +++ b/mk/rte.app.mk @@ -100,7 +100,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE) += -lrte_cmdline _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE) += -lrte_cfgfile _LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS) += -lrte_metrics _LDLIBS-$(CONFIG_RTE_LIBRTE_BITRATE) += -lrte_bitratestats - +_LDLIBS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += -lrte_latencystats _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += -lrte_pmd_bond _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += -lrte_pmd_xenvirt -lxenstore -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v6 0/4] Expanded statistics reporting 2016-11-18 8:00 ` [dpdk-dev] [PATCH v5 0/4] Expanded statistics reporting Remy Horton ` (3 preceding siblings ...) 2016-11-18 8:00 ` [dpdk-dev] [PATCH v5 4/4] latencystats: added new library for latency stats Remy Horton @ 2017-01-11 16:03 ` Remy Horton 2017-01-11 16:03 ` [dpdk-dev] [PATCH v6 1/4] lib: add information metrics library Remy Horton ` (5 more replies) 4 siblings, 6 replies; 115+ messages in thread From: Remy Horton @ 2017-01-11 16:03 UTC (permalink / raw) To: dev; +Cc: Thomas Monjalon This patchset extends statistics reporting to include peak and average data-rate metrics. It comes in two parts: a statistics reporting library, and a bitrate calculation library that uses it. This structure is intended to seperate statistic reporting from ethdev and allow more flexible metric registration. Due to merge issues Reshma's latency statistics, which depends on the reporting library, has been merged into this patchset. -- v6 changes: * Metrics display now has "Non port specific" rather than "port -1" * Fixed sign issue in EWMA delta calculation * Rebased to master v5 changes: * Updated Shared Library Versions in release notes * Merged in Reshma's latencystats library v4 changes: * References to 16.11 changed to 17.02 * Fetching of non-port values was broken * Added sanity checks to value fetching * rte_stat_value renamed to rte_metric_value * Corrected doxygen descriptions * Added MAINTAINERS entries * Added #ifdef directives to bitrate code in test-pmd v3 changes: * Marked rte_stats_bitrate_s as internal * Minor integer roundoff correction * Coding style corrections * Removed spurious object allocation * Changes to rte_metrics.[ch] moved from Patch 2/3 to 1/3. * Reintroduced non-port values (RTE_METRICS_NONPORT) * Added spinlocks to metric library * Removed spurious test registration/update * Added release notes entries v2 changes: * Uses a new metrics library rather than being part of ethdev Remy Horton (4): lib: add information metrics library lib: add bitrate statistics library app/test-pmd: add support for bitrate statistics latencystats: added new library for latency stats MAINTAINERS | 13 + app/proc_info/main.c | 73 ++++ app/test-pmd/testpmd.c | 46 +++ config/common_base | 15 + doc/api/doxy-api-index.md | 3 + doc/api/doxy-api.conf | 3 + doc/guides/rel_notes/release_17_02.rst | 18 + lib/Makefile | 3 + lib/librte_bitratestats/Makefile | 53 +++ lib/librte_bitratestats/rte_bitrate.c | 131 +++++++ lib/librte_bitratestats/rte_bitrate.h | 80 +++++ .../rte_bitratestats_version.map | 9 + lib/librte_latencystats/Makefile | 57 +++ lib/librte_latencystats/rte_latencystats.c | 389 +++++++++++++++++++++ lib/librte_latencystats/rte_latencystats.h | 146 ++++++++ .../rte_latencystats_version.map | 10 + lib/librte_mbuf/rte_mbuf.h | 3 + lib/librte_metrics/Makefile | 51 +++ lib/librte_metrics/rte_metrics.c | 308 ++++++++++++++++ lib/librte_metrics/rte_metrics.h | 190 ++++++++++ lib/librte_metrics/rte_metrics_version.map | 13 + mk/rte.app.mk | 3 + 22 files changed, 1617 insertions(+) create mode 100644 lib/librte_bitratestats/Makefile create mode 100644 lib/librte_bitratestats/rte_bitrate.c create mode 100644 lib/librte_bitratestats/rte_bitrate.h create mode 100644 lib/librte_bitratestats/rte_bitratestats_version.map create mode 100644 lib/librte_latencystats/Makefile create mode 100644 lib/librte_latencystats/rte_latencystats.c create mode 100644 lib/librte_latencystats/rte_latencystats.h create mode 100644 lib/librte_latencystats/rte_latencystats_version.map create mode 100644 lib/librte_metrics/Makefile create mode 100644 lib/librte_metrics/rte_metrics.c create mode 100644 lib/librte_metrics/rte_metrics.h create mode 100644 lib/librte_metrics/rte_metrics_version.map -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v6 1/4] lib: add information metrics library 2017-01-11 16:03 ` [dpdk-dev] [PATCH v6 0/4] Expanded statistics reporting Remy Horton @ 2017-01-11 16:03 ` Remy Horton 2017-01-12 13:22 ` Thomas Monjalon 2017-01-11 16:03 ` [dpdk-dev] [PATCH v6 2/4] lib: add bitrate statistics library Remy Horton ` (4 subsequent siblings) 5 siblings, 1 reply; 115+ messages in thread From: Remy Horton @ 2017-01-11 16:03 UTC (permalink / raw) To: dev; +Cc: Thomas Monjalon This patch adds a new information metric library that allows other modules to register named metrics and update their values. It is intended to be independent of ethdev, rather than mixing ethdev and non-ethdev information in xstats. Signed-off-by: Remy Horton <remy.horton@intel.com> --- MAINTAINERS | 5 + config/common_base | 5 + doc/api/doxy-api-index.md | 1 + doc/api/doxy-api.conf | 1 + doc/guides/rel_notes/release_17_02.rst | 7 + lib/Makefile | 1 + lib/librte_metrics/Makefile | 51 +++++ lib/librte_metrics/rte_metrics.c | 308 +++++++++++++++++++++++++++++ lib/librte_metrics/rte_metrics.h | 190 ++++++++++++++++++ lib/librte_metrics/rte_metrics_version.map | 13 ++ mk/rte.app.mk | 2 + 11 files changed, 584 insertions(+) create mode 100644 lib/librte_metrics/Makefile create mode 100644 lib/librte_metrics/rte_metrics.c create mode 100644 lib/librte_metrics/rte_metrics.h create mode 100644 lib/librte_metrics/rte_metrics_version.map diff --git a/MAINTAINERS b/MAINTAINERS index 9645c9b..4a19497 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -596,6 +596,11 @@ F: lib/librte_jobstats/ F: examples/l2fwd-jobstats/ F: doc/guides/sample_app_ug/l2_forward_job_stats.rst +Metrics +M: Remy Horton <remy.horton@intel.com> +F: lib/librte_metrics/ +F: doc/guides/sample_app_ug/keep_alive.rst + Test Applications ----------------- diff --git a/config/common_base b/config/common_base index 8e9dcfa..0eb3866 100644 --- a/config/common_base +++ b/config/common_base @@ -593,3 +593,8 @@ CONFIG_RTE_APP_TEST_RESOURCE_TAR=n CONFIG_RTE_TEST_PMD=y CONFIG_RTE_TEST_PMD_RECORD_CORE_CYCLES=n CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n + +# +# Compile the device metrics library +# +CONFIG_RTE_LIBRTE_METRICS=y diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md index 72d59b2..94f0f69 100644 --- a/doc/api/doxy-api-index.md +++ b/doc/api/doxy-api-index.md @@ -150,4 +150,5 @@ There are many libraries, so their headers may be grouped by topics: [common] (@ref rte_common.h), [ABI compat] (@ref rte_compat.h), [keepalive] (@ref rte_keepalive.h), + [Device Metrics] (@ref rte_metrics.h), [version] (@ref rte_version.h) diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf index b340fcf..13e0faf 100644 --- a/doc/api/doxy-api.conf +++ b/doc/api/doxy-api.conf @@ -58,6 +58,7 @@ INPUT = doc/api/doxy-api-index.md \ lib/librte_reorder \ lib/librte_ring \ lib/librte_sched \ + lib/librte_metrics \ lib/librte_table \ lib/librte_timer \ lib/librte_vhost diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst index 180af82..82c5616 100644 --- a/doc/guides/rel_notes/release_17_02.rst +++ b/doc/guides/rel_notes/release_17_02.rst @@ -34,6 +34,12 @@ New Features Refer to the previous release notes for examples. + * **Added information metric library.** + + A library that allows information metrics to be added and update. It is + intended to provide a reporting mechanism that is independent of the + ethdev library. + This section is a comment. do not overwrite or remove it. Also, make sure to start the actual text at the margin. ========================================================= @@ -171,6 +177,7 @@ The libraries prepended with a plus sign were incremented in this version. librte_mbuf.so.2 librte_mempool.so.2 librte_meter.so.1 + + librte_metrics.so.1 librte_net.so.1 librte_pdump.so.1 librte_pipeline.so.3 diff --git a/lib/Makefile b/lib/Makefile index 990f23a..5d85dcf 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -58,6 +58,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_TABLE) += librte_table DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += librte_pipeline DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump +DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni diff --git a/lib/librte_metrics/Makefile b/lib/librte_metrics/Makefile new file mode 100644 index 0000000..8d6e23a --- /dev/null +++ b/lib/librte_metrics/Makefile @@ -0,0 +1,51 @@ +# BSD LICENSE +# +# Copyright(c) 2016 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +include $(RTE_SDK)/mk/rte.vars.mk + +# library name +LIB = librte_metrics.a + +CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) + +EXPORT_MAP := rte_metrics_version.map + +LIBABIVER := 1 + +# all source are stored in SRCS-y +SRCS-$(CONFIG_RTE_LIBRTE_METRICS) := rte_metrics.c + +# Install header file +SYMLINK-$(CONFIG_RTE_LIBRTE_METRICS)-include += rte_metrics.h + +DEPDIRS-$(CONFIG_RTE_LIBRTE_METRICS) += lib/librte_eal + +include $(RTE_SDK)/mk/rte.lib.mk diff --git a/lib/librte_metrics/rte_metrics.c b/lib/librte_metrics/rte_metrics.c new file mode 100644 index 0000000..5edacc6 --- /dev/null +++ b/lib/librte_metrics/rte_metrics.c @@ -0,0 +1,308 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <string.h> +#include <sys/queue.h> + +#include <rte_common.h> +#include <rte_malloc.h> +#include <rte_metrics.h> +#include <rte_lcore.h> +#include <rte_memzone.h> +#include <rte_spinlock.h> + +#define RTE_METRICS_MAX_METRICS 256 +#define RTE_METRICS_MEMZONE_NAME "RTE_METRICS" + +/** + * Internal stats metadata and value entry. + * + * @internal + * @param name + * Name of metric + * @param value + * Current value for metric + * @param idx_next_set + * Index of next root element (zero for none) + * @param idx_next_metric + * Index of next metric in set (zero for none) + * + * Only the root of each set needs idx_next_set but since it has to be + * assumed that number of sets could equal total number of metrics, + * having a separate set metadata table doesn't save any memory. + */ +struct rte_metrics_meta_s { + char name[RTE_METRICS_MAX_NAME_LEN]; + uint64_t value[RTE_MAX_ETHPORTS]; + uint64_t nonport_value; + uint16_t idx_next_set; + uint16_t idx_next_stat; +}; + +/** + * Internal stats info structure. + * + * @internal + * @param idx_last_set + * Index of last metadata entry with valid data. This value is + * not valid if cnt_stats is zero. + * @param cnt_stats + * Number of metrics. + * @param metadata + * Stat data memory block. + * + * Offsets into metadata are used instead of pointers because ASLR + * means that having the same physical addresses in different + * processes is not guaranteed. + */ +struct rte_metrics_data_s { + uint16_t idx_last_set; + uint16_t cnt_stats; + struct rte_metrics_meta_s metadata[RTE_METRICS_MAX_METRICS]; + rte_spinlock_t lock; +}; + +void +rte_metrics_init(void) +{ + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + + if (rte_eal_process_type() != RTE_PROC_PRIMARY) + return; + + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); + if (memzone != NULL) + return; + memzone = rte_memzone_reserve(RTE_METRICS_MEMZONE_NAME, + sizeof(struct rte_metrics_data_s), rte_socket_id(), 0); + if (memzone == NULL) + rte_exit(EXIT_FAILURE, "Unable to allocate stats memzone\n"); + stats = memzone->addr; + memset(stats, 0, sizeof(struct rte_metrics_data_s)); + rte_spinlock_init(&stats->lock); +} + +int +rte_metrics_reg_metric(const char *name) +{ + const char *list_names[] = {name}; + + return rte_metrics_reg_metrics(list_names, 1); +} + +int +rte_metrics_reg_metrics(const char **names, uint16_t cnt_names) +{ + struct rte_metrics_meta_s *entry; + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + uint16_t idx_name; + uint16_t idx_base; + + /* Some sanity checks */ + if (cnt_names < 1 || names == NULL) + return -EINVAL; + + rte_metrics_init(); + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); + if (memzone == NULL) + return -EIO; + stats = memzone->addr; + + if (stats->cnt_stats + cnt_names >= RTE_METRICS_MAX_METRICS) + return -ENOMEM; + + rte_spinlock_lock(&stats->lock); + + /* Overwritten later if this is actually first set.. */ + stats->metadata[stats->idx_last_set].idx_next_set = stats->cnt_stats; + + stats->idx_last_set = idx_base = stats->cnt_stats; + + for (idx_name = 0; idx_name < cnt_names; idx_name++) { + entry = &stats->metadata[idx_name + stats->cnt_stats]; + strncpy(entry->name, names[idx_name], + RTE_METRICS_MAX_NAME_LEN); + memset(entry->value, 0, sizeof(entry->value)); + entry->idx_next_stat = idx_name + stats->cnt_stats + 1; + } + entry->idx_next_stat = 0; + entry->idx_next_set = 0; + stats->cnt_stats += cnt_names; + + rte_spinlock_unlock(&stats->lock); + + return idx_base; +} + +int +rte_metrics_update_metric(int port_id, uint16_t key, const uint64_t value) +{ + return rte_metrics_update_metrics(port_id, key, &value, 1); +} + +int +rte_metrics_update_metrics(int port_id, + uint16_t key, + const uint64_t *values, + uint32_t count) +{ + struct rte_metrics_meta_s *entry; + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + uint16_t idx_metric; + uint16_t idx_value; + uint16_t cnt_setsize; + + if (port_id != RTE_METRICS_NONPORT && + (port_id < 0 || port_id > RTE_MAX_ETHPORTS)) + return -EINVAL; + + rte_metrics_init(); + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); + if (memzone == NULL) + return -EIO; + stats = memzone->addr; + + rte_spinlock_lock(&stats->lock); + idx_metric = key; + cnt_setsize = 1; + while (idx_metric < stats->cnt_stats) { + entry = &stats->metadata[idx_metric]; + if (entry->idx_next_stat == 0) + break; + cnt_setsize++; + idx_metric++; + } + /* Check update does not cross set border */ + if (count > cnt_setsize) { + rte_spinlock_unlock(&stats->lock); + return -ERANGE; + } + + if (port_id == RTE_METRICS_NONPORT) + for (idx_value = 0; idx_value < count; idx_value++) { + idx_metric = key + idx_value; + stats->metadata[idx_metric].nonport_value = + values[idx_value]; + } + else + for (idx_value = 0; idx_value < count; idx_value++) { + idx_metric = key + idx_value; + stats->metadata[idx_metric].value[port_id] = + values[idx_value]; + } + rte_spinlock_unlock(&stats->lock); + return 0; +} + +int +rte_metrics_get_names(struct rte_metric_name *names, + uint16_t capacity) +{ + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + uint16_t idx_name; + int return_value; + + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); + /* If not allocated, fail silently */ + if (memzone == NULL) + return 0; + + stats = memzone->addr; + rte_spinlock_lock(&stats->lock); + if (names != NULL) { + if (capacity < stats->cnt_stats) { + rte_spinlock_unlock(&stats->lock); + return -ERANGE; + } + for (idx_name = 0; idx_name < stats->cnt_stats; idx_name++) + strncpy(names[idx_name].name, + stats->metadata[idx_name].name, + RTE_METRICS_MAX_NAME_LEN); + } + return_value = stats->cnt_stats; + rte_spinlock_unlock(&stats->lock); + return return_value; +} + +int +rte_metrics_get_values(int port_id, + struct rte_metric_value *values, + uint16_t capacity) +{ + struct rte_metrics_meta_s *entry; + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + uint16_t idx_name; + int return_value; + + if (port_id != RTE_METRICS_NONPORT && + (port_id < 0 || port_id > RTE_MAX_ETHPORTS)) + return -EINVAL; + + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); + /* If not allocated, fail silently */ + if (memzone == NULL) + return 0; + stats = memzone->addr; + rte_spinlock_lock(&stats->lock); + + if (values != NULL) { + if (capacity < stats->cnt_stats) { + rte_spinlock_unlock(&stats->lock); + return -ERANGE; + } + if (port_id == RTE_METRICS_NONPORT) + for (idx_name = 0; + idx_name < stats->cnt_stats; + idx_name++) { + entry = &stats->metadata[idx_name]; + values[idx_name].key = idx_name; + values[idx_name].value = entry->nonport_value; + } + else + for (idx_name = 0; + idx_name < stats->cnt_stats; + idx_name++) { + entry = &stats->metadata[idx_name]; + values[idx_name].key = idx_name; + values[idx_name].value = entry->value[port_id]; + } + } + return_value = stats->cnt_stats; + rte_spinlock_unlock(&stats->lock); + return return_value; +} diff --git a/lib/librte_metrics/rte_metrics.h b/lib/librte_metrics/rte_metrics.h new file mode 100644 index 0000000..c58b366 --- /dev/null +++ b/lib/librte_metrics/rte_metrics.h @@ -0,0 +1,190 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * + * RTE Metrics module + * + * Metric information is populated using a push model, where the + * information provider calls an update function on the relevant + * metrics. Currently only bulk querying of metrics is supported. + */ + +#ifndef _RTE_METRICS_H_ +#define _RTE_METRICS_H_ + +/** Maximum length of metric name (including null-terminator) */ +#define RTE_METRICS_MAX_NAME_LEN 64 + +/** Used to indicate port-independent information */ +#define RTE_METRICS_NONPORT -1 + + +/** + * Metric name + */ +struct rte_metric_name { + /** String describing metric */ + char name[RTE_METRICS_MAX_NAME_LEN]; +}; + + +/** + * Metric name. + */ +struct rte_metric_value { + /** Numeric identifier of metric */ + uint16_t key; + /** Value for metric */ + uint64_t value; +}; + + +/** + * Initializes metric module. This only has to be explicitly called if you + * intend to use rte_metrics_reg_metric() or rte_metrics_reg_metrics() from a + * secondary process. This function must be called from a primary process. + */ +void rte_metrics_init(void); + + +/** + * Register a metric + * + * @param name + * Metric name + * + * @return + * - Zero or positive: Success + * - Negative: Failure + */ +int rte_metrics_reg_metric(const char *name); + +/** + * Register a set of metrics + * + * @param names + * List of metric names + * + * @param cnt_names + * Number of metrics in set + * + * @return + * - Zero or positive: Success + * - Negative: Failure + */ +int rte_metrics_reg_metrics(const char **names, uint16_t cnt_names); + +/** + * Get metric name-key lookup table. + * + * @param names + * Array of names to receive key names + * + * @param capacity + * Space available in names + * + * @return + * - Non-negative: Success (number of names) + * - Negative: Failure + */ +int rte_metrics_get_names( + struct rte_metric_name *names, + uint16_t capacity); + +/** + * Fetch metrics. + * + * @param port_id + * Port id to query + * + * @param values + * Array to receive values and their keys + * + * @param capacity + * Space available in values + * + * @return + * - Non-negative: Success (number of names) + * - Negative: Failure + */ +int rte_metrics_get_values( + int port_id, + struct rte_metric_value *values, + uint16_t capacity); + +/** + * Updates a metric + * + * @param port_id + * Port to update metrics for + * @param key + * Id of metric to update + * @param value + * New value + * + * @return + * - -EIO if unable to access shared metrics memory + * - Zero on success + */ +int rte_metrics_update_metric( + int port_id, + uint16_t key, + const uint64_t value); + +/** + * Updates a metric set. Note that it is an error to try to + * update across a set boundary. + * + * @param port_id + * Port to update metrics for + * @param key + * Base id of metrics set to update + * @param values + * Set of new values + * @param count + * Number of new values + * + * @return + * - -ERANGE if count exceeds metric set size + * - -EIO if upable to access shared metrics memory + * - Zero on success + */ +int rte_metrics_update_metrics( + int port_id, + uint16_t key, + const uint64_t *values, + uint32_t count); + +#endif diff --git a/lib/librte_metrics/rte_metrics_version.map b/lib/librte_metrics/rte_metrics_version.map new file mode 100644 index 0000000..f904814 --- /dev/null +++ b/lib/librte_metrics/rte_metrics_version.map @@ -0,0 +1,13 @@ +DPDK_17.02 { + global: + + rte_metrics_get_names; + rte_metrics_get_values; + rte_metrics_init; + rte_metrics_reg_metric; + rte_metrics_reg_metrics; + rte_metrics_update_metric; + rte_metrics_update_metrics; + + local: *; +}; diff --git a/mk/rte.app.mk b/mk/rte.app.mk index f75f0e2..40fcf33 100644 --- a/mk/rte.app.mk +++ b/mk/rte.app.mk @@ -98,6 +98,8 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_RING) += -lrte_ring _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL) += -lrte_eal _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE) += -lrte_cmdline _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE) += -lrte_cfgfile +_LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS) += -lrte_metrics + _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += -lrte_pmd_bond _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += -lrte_pmd_xenvirt -lxenstore -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [PATCH v6 1/4] lib: add information metrics library 2017-01-11 16:03 ` [dpdk-dev] [PATCH v6 1/4] lib: add information metrics library Remy Horton @ 2017-01-12 13:22 ` Thomas Monjalon 2017-01-12 15:30 ` Remy Horton 0 siblings, 1 reply; 115+ messages in thread From: Thomas Monjalon @ 2017-01-12 13:22 UTC (permalink / raw) To: Remy Horton; +Cc: dev 2017-01-12 00:03, Remy Horton: > This patch adds a new information metric library that allows other > modules to register named metrics and update their values. It is > intended to be independent of ethdev, rather than mixing ethdev > and non-ethdev information in xstats. [...] > --- a/doc/api/doxy-api.conf > +++ b/doc/api/doxy-api.conf > @@ -58,6 +58,7 @@ INPUT = doc/api/doxy-api-index.md \ > lib/librte_reorder \ > lib/librte_ring \ > lib/librte_sched \ > + lib/librte_metrics \ > lib/librte_table \ > lib/librte_timer \ > lib/librte_vhost It is not in the right order. Tip: when you add an item to a list, you should ask yourself what is the order. There are 3 types of order for the lists in DPDK: - chronological (add at the end) - alphabetical - logical/semantic The game is to find the right one :) [...] > @@ -171,6 +177,7 @@ The libraries prepended with a plus sign were incremented in this version. > librte_mbuf.so.2 > librte_mempool.so.2 > librte_meter.so.1 > + + librte_metrics.so.1 > librte_net.so.1 > librte_pdump.so.1 > librte_pipeline.so.3 Right order here ;) [...] > --- /dev/null > +++ b/lib/librte_metrics/rte_metrics.h > +/** Used to indicate port-independent information */ > +#define RTE_METRICS_NONPORT -1 I do not understand this constant. Why using the word "port" to name any device? What means independent? > +/** > + * Metric name > + */ > +struct rte_metric_name { > + /** String describing metric */ > + char name[RTE_METRICS_MAX_NAME_LEN]; > +}; Why a struct for a simple string? > +/** > + * Metric name. Copy/paste typo? > + */ > +struct rte_metric_value { > + /** Numeric identifier of metric */ > + uint16_t key; How the key is bound to the name? Remember how the xstats comments were improved: http://dpdk.org/commit/6d52d1d > + /** Value for metric */ > + uint64_t value; > +}; > + > + > +/** > + * Initializes metric module. This only has to be explicitly called if you > + * intend to use rte_metrics_reg_metric() or rte_metrics_reg_metrics() from a > + * secondary process. This function must be called from a primary process. > + */ > +void rte_metrics_init(void); > + > + > +/** > + * Register a metric You need to explain what is implied in registering. I have the same comment for registering a set of metrics. [...] > +int rte_metrics_reg_metric(const char *name); > + > +/** > + * Register a set of metrics [...] > +int rte_metrics_reg_metrics(const char **names, uint16_t cnt_names); > + > +/** > + * Get metric name-key lookup table. > + * > + * @param names > + * Array of names to receive key names > + * > + * @param capacity > + * Space available in names What happens if there is not enough space? > + * @return > + * - Non-negative: Success (number of names) > + * - Negative: Failure > + */ > +int rte_metrics_get_names( > + struct rte_metric_name *names, > + uint16_t capacity); ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [PATCH v6 1/4] lib: add information metrics library 2017-01-12 13:22 ` Thomas Monjalon @ 2017-01-12 15:30 ` Remy Horton 2017-01-12 19:05 ` Thomas Monjalon 0 siblings, 1 reply; 115+ messages in thread From: Remy Horton @ 2017-01-12 15:30 UTC (permalink / raw) To: Thomas Monjalon; +Cc: dev On 12/01/2017 13:22, Thomas Monjalon wrote: > 2017-01-12 00:03, Remy Horton: [..] >> --- /dev/null >> +++ b/lib/librte_metrics/rte_metrics.h >> +/** Used to indicate port-independent information */ >> +#define RTE_METRICS_NONPORT -1 > > I do not understand this constant. > Why using the word "port" to name any device? > What means independent? The metric library hold two sets of values: Ones specific to ports, and ones that are global/aggregate. Agree "non port" is not the clearest choice of name.. >> +/** >> + * Metric name >> + */ >> +struct rte_metric_name { >> + /** String describing metric */ >> + char name[RTE_METRICS_MAX_NAME_LEN]; >> +}; > > Why a struct for a simple string? It is modelled after xstats, which does the same thing. In this case thinking was that using: rte_metrics_get_names(struct rte_metric_name *names, uint16_t capacity) would be tidier than (e.g.): rte_metrics_get_names(char *names[RTE_METRICS_MAX_NAME_LEN], uint16_t capacity) >> + */ >> +struct rte_metric_value { >> + /** Numeric identifier of metric */ >> + uint16_t key; > > How the key is bound to the name? Corresponds to array position in struct rte_metric_name. Will amend doxygen comments. > Remember how the xstats comments were improved: > http://dpdk.org/commit/6d52d1d Will take account for them. I wrote this code back in October, so it slipped my mind to apply the same comments to this module. ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [PATCH v6 1/4] lib: add information metrics library 2017-01-12 15:30 ` Remy Horton @ 2017-01-12 19:05 ` Thomas Monjalon 2017-01-16 10:27 ` Remy Horton 0 siblings, 1 reply; 115+ messages in thread From: Thomas Monjalon @ 2017-01-12 19:05 UTC (permalink / raw) To: Remy Horton; +Cc: dev 2017-01-12 15:30, Remy Horton: > > On 12/01/2017 13:22, Thomas Monjalon wrote: > > 2017-01-12 00:03, Remy Horton: > [..] > >> --- /dev/null > >> +++ b/lib/librte_metrics/rte_metrics.h > >> +/** Used to indicate port-independent information */ > >> +#define RTE_METRICS_NONPORT -1 > > > > I do not understand this constant. > > Why using the word "port" to name any device? > > What means independent? > > The metric library hold two sets of values: Ones specific to ports, and > ones that are global/aggregate. Agree "non port" is not the clearest > choice of name.. I think you should not use the word "port" at all. ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [PATCH v6 1/4] lib: add information metrics library 2017-01-12 19:05 ` Thomas Monjalon @ 2017-01-16 10:27 ` Remy Horton 0 siblings, 0 replies; 115+ messages in thread From: Remy Horton @ 2017-01-16 10:27 UTC (permalink / raw) To: Thomas Monjalon; +Cc: dev On 12/01/2017 19:05, Thomas Monjalon wrote: > 2017-01-12 15:30, Remy Horton: [..] >> The metric library hold two sets of values: Ones specific to ports, and >> ones that are global/aggregate. Agree "non port" is not the clearest >> choice of name.. > > I think you should not use the word "port" at all. > Changing it is on the todo list.. :) ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v6 2/4] lib: add bitrate statistics library 2017-01-11 16:03 ` [dpdk-dev] [PATCH v6 0/4] Expanded statistics reporting Remy Horton 2017-01-11 16:03 ` [dpdk-dev] [PATCH v6 1/4] lib: add information metrics library Remy Horton @ 2017-01-11 16:03 ` Remy Horton 2017-01-11 16:15 ` Stephen Hemminger 2017-01-11 16:03 ` [dpdk-dev] [PATCH v6 3/4] app/test-pmd: add support for bitrate statistics Remy Horton ` (3 subsequent siblings) 5 siblings, 1 reply; 115+ messages in thread From: Remy Horton @ 2017-01-11 16:03 UTC (permalink / raw) To: dev; +Cc: Thomas Monjalon This patch adds a library that calculates peak and average data-rate statistics. For ethernet devices. These statistics are reported using the metrics library. Signed-off-by: Remy Horton <remy.horton@intel.com> --- MAINTAINERS | 4 + config/common_base | 5 + doc/api/doxy-api-index.md | 1 + doc/api/doxy-api.conf | 1 + doc/guides/rel_notes/release_17_02.rst | 6 + lib/Makefile | 1 + lib/librte_bitratestats/Makefile | 53 +++++++++ lib/librte_bitratestats/rte_bitrate.c | 131 +++++++++++++++++++++ lib/librte_bitratestats/rte_bitrate.h | 80 +++++++++++++ .../rte_bitratestats_version.map | 9 ++ mk/rte.app.mk | 1 + 11 files changed, 292 insertions(+) create mode 100644 lib/librte_bitratestats/Makefile create mode 100644 lib/librte_bitratestats/rte_bitrate.c create mode 100644 lib/librte_bitratestats/rte_bitrate.h create mode 100644 lib/librte_bitratestats/rte_bitratestats_version.map diff --git a/MAINTAINERS b/MAINTAINERS index 4a19497..6cd9896 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -601,6 +601,10 @@ M: Remy Horton <remy.horton@intel.com> F: lib/librte_metrics/ F: doc/guides/sample_app_ug/keep_alive.rst +Bit-rate statistica +M: Remy Horton <remy.horton@intel.com> +F: lib/librte_bitratestats/ + Test Applications ----------------- diff --git a/config/common_base b/config/common_base index 0eb3866..decebe5 100644 --- a/config/common_base +++ b/config/common_base @@ -598,3 +598,8 @@ CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n # Compile the device metrics library # CONFIG_RTE_LIBRTE_METRICS=y + +# +# Compile the bitrate statistics library +# +CONFIG_RTE_LIBRTE_BITRATE=y diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md index 94f0f69..5e194b0 100644 --- a/doc/api/doxy-api-index.md +++ b/doc/api/doxy-api-index.md @@ -151,4 +151,5 @@ There are many libraries, so their headers may be grouped by topics: [ABI compat] (@ref rte_compat.h), [keepalive] (@ref rte_keepalive.h), [Device Metrics] (@ref rte_metrics.h), + [Bitrate Statistics] (@ref rte_bitrate.h), [version] (@ref rte_version.h) diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf index 13e0faf..ff15f5b 100644 --- a/doc/api/doxy-api.conf +++ b/doc/api/doxy-api.conf @@ -59,6 +59,7 @@ INPUT = doc/api/doxy-api-index.md \ lib/librte_ring \ lib/librte_sched \ lib/librte_metrics \ + lib/librte_bitratestats \ lib/librte_table \ lib/librte_timer \ lib/librte_vhost diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst index 82c5616..70f93e1 100644 --- a/doc/guides/rel_notes/release_17_02.rst +++ b/doc/guides/rel_notes/release_17_02.rst @@ -40,6 +40,11 @@ New Features intended to provide a reporting mechanism that is independent of the ethdev library. + * **Added bit-rate calculation library.** + + A library that can be used to calculate device bit-rates. Calculated + bitrates are reported using the metrics library. + This section is a comment. do not overwrite or remove it. Also, make sure to start the actual text at the margin. ========================================================= @@ -162,6 +167,7 @@ The libraries prepended with a plus sign were incremented in this version. .. code-block:: diff librte_acl.so.2 + + librte_bitratestats.so.1 librte_cfgfile.so.2 librte_cmdline.so.2 librte_cryptodev.so.2 diff --git a/lib/Makefile b/lib/Makefile index 5d85dcf..e211bc0 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -59,6 +59,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += librte_pipeline DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics +DIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += librte_bitratestats ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni diff --git a/lib/librte_bitratestats/Makefile b/lib/librte_bitratestats/Makefile new file mode 100644 index 0000000..b725d4e --- /dev/null +++ b/lib/librte_bitratestats/Makefile @@ -0,0 +1,53 @@ +# BSD LICENSE +# +# Copyright(c) 2016 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +include $(RTE_SDK)/mk/rte.vars.mk + +# library name +LIB = librte_bitratestats.a + +CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) + +EXPORT_MAP := rte_bitratestats_version.map + +LIBABIVER := 1 + +# all source are stored in SRCS-y +SRCS-$(CONFIG_RTE_LIBRTE_BITRATE) := rte_bitrate.c + +# Install header file +SYMLINK-$(CONFIG_RTE_LIBRTE_BITRATE)-include += rte_bitrate.h + +DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_eal +DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_ether +DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_metrics + +include $(RTE_SDK)/mk/rte.lib.mk diff --git a/lib/librte_bitratestats/rte_bitrate.c b/lib/librte_bitratestats/rte_bitrate.c new file mode 100644 index 0000000..cb7aae4 --- /dev/null +++ b/lib/librte_bitratestats/rte_bitrate.c @@ -0,0 +1,131 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <rte_common.h> +#include <rte_ethdev.h> +#include <rte_malloc.h> +#include <rte_metrics.h> +#include <rte_bitrate.h> + +/* + * Persistent bit-rate data. + * @internal + */ +struct rte_stats_bitrate_s { + uint64_t last_ibytes; + uint64_t last_obytes; + uint64_t peak_ibits; + uint64_t peak_obits; + uint64_t ewma_ibits; + uint64_t ewma_obits; +}; + +struct rte_stats_bitrates_s { + struct rte_stats_bitrate_s port_stats[RTE_MAX_ETHPORTS]; + uint16_t id_stats_set; +}; + +struct rte_stats_bitrates_s * +rte_stats_bitrate_create(void) +{ + return rte_zmalloc(NULL, sizeof(struct rte_stats_bitrates_s), 0); +} + +int +rte_stats_bitrate_reg(struct rte_stats_bitrates_s *bitrate_data) +{ + const char *names[] = { + "mean_bits_in", "mean_bits_out", + "peak_bits_in", "peak_bits_out", + }; + int return_value; + + return_value = rte_metrics_reg_metrics(&names[0], 4); + if (return_value >= 0) + bitrate_data->id_stats_set = return_value; + return return_value; +} + +int +rte_stats_bitrate_calc(struct rte_stats_bitrates_s *bitrate_data, + uint8_t port_id) +{ + struct rte_stats_bitrate_s *port_data; + struct rte_eth_stats eth_stats; + int ret_code; + uint64_t cnt_bits; + int64_t delta; + const int64_t alpha_percent = 20; + uint64_t values[4]; + + ret_code = rte_eth_stats_get(port_id, ð_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 [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [PATCH v6 2/4] lib: add bitrate statistics library 2017-01-11 16:03 ` [dpdk-dev] [PATCH v6 2/4] lib: add bitrate statistics library Remy Horton @ 2017-01-11 16:15 ` Stephen Hemminger 2017-01-16 13:18 ` Remy Horton 0 siblings, 1 reply; 115+ messages in thread From: Stephen Hemminger @ 2017-01-11 16:15 UTC (permalink / raw) To: Remy Horton; +Cc: dev, Thomas Monjalon On Thu, 12 Jan 2017 00:03:12 +0800 Remy Horton <remy.horton@intel.com> wrote: > + > +struct rte_stats_bitrates_s * > +rte_stats_bitrate_create(void) > +{ > + return rte_zmalloc(NULL, sizeof(struct rte_stats_bitrates_s), 0); > +} > + You want these statistics to be cache aligned (ie not 0) to avoid false cache sharing. Since these statistics are often associated with a device would it not make sense to have a NUMA socket associated with the alllocation? ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [PATCH v6 2/4] lib: add bitrate statistics library 2017-01-11 16:15 ` Stephen Hemminger @ 2017-01-16 13:18 ` Remy Horton 0 siblings, 0 replies; 115+ messages in thread From: Remy Horton @ 2017-01-16 13:18 UTC (permalink / raw) To: Stephen Hemminger; +Cc: dev, Thomas Monjalon On 11/01/2017 16:15, Stephen Hemminger wrote: [..] > You want these statistics to be cache aligned (ie not 0) to avoid > false cache sharing. Done. > Since these statistics are often associated with a device would it > not make sense to have a NUMA socket associated with the alllocation? Makes sense, although given the intended frequency of access and the amount of data, not sure it would gain much. ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v6 3/4] app/test-pmd: add support for bitrate statistics 2017-01-11 16:03 ` [dpdk-dev] [PATCH v6 0/4] Expanded statistics reporting Remy Horton 2017-01-11 16:03 ` [dpdk-dev] [PATCH v6 1/4] lib: add information metrics library Remy Horton 2017-01-11 16:03 ` [dpdk-dev] [PATCH v6 2/4] lib: add bitrate statistics library Remy Horton @ 2017-01-11 16:03 ` Remy Horton 2017-01-12 13:32 ` Thomas Monjalon 2017-01-11 16:03 ` [dpdk-dev] [PATCH v6 4/4] latencystats: added new library for latency stats Remy Horton ` (2 subsequent siblings) 5 siblings, 1 reply; 115+ messages in thread From: Remy Horton @ 2017-01-11 16:03 UTC (permalink / raw) To: dev; +Cc: Thomas Monjalon Signed-off-by: Remy Horton <remy.horton@intel.com> --- app/test-pmd/testpmd.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c index bfb2f8e..a0b7430 100644 --- a/app/test-pmd/testpmd.c +++ b/app/test-pmd/testpmd.c @@ -79,6 +79,10 @@ #include <rte_pdump.h> #endif #include <rte_flow.h> +#include <rte_metrics.h> +#ifdef RTE_LIBRTE_BITRATE +#include <rte_bitrate.h> +#endif #include "testpmd.h" @@ -323,6 +327,9 @@ uint16_t nb_rx_queue_stats_mappings = 0; unsigned max_socket = 0; +/* Bitrate statistics */ +struct rte_stats_bitrates_s *bitrate_data; + /* Forward function declarations */ static void map_port_queue_stats_mapping_registers(uint8_t pi, struct rte_port *port); static void check_all_ports_link_status(uint32_t port_mask); @@ -922,12 +929,32 @@ run_pkt_fwd_on_lcore(struct fwd_lcore *fc, packet_fwd_t pkt_fwd) struct fwd_stream **fsm; streamid_t nb_fs; streamid_t sm_id; +#ifdef RTE_LIBRTE_BITRATE + uint64_t tics_per_1sec; + uint64_t tics_datum; + uint64_t tics_current; + uint8_t idx_port, cnt_ports; +#endif +#ifdef RTE_LIBRTE_BITRATE + cnt_ports = rte_eth_dev_count(); + tics_datum = rte_rdtsc(); + tics_per_1sec = rte_get_timer_hz(); +#endif fsm = &fwd_streams[fc->stream_idx]; nb_fs = fc->stream_nb; do { for (sm_id = 0; sm_id < nb_fs; sm_id++) (*pkt_fwd)(fsm[sm_id]); +#ifdef RTE_LIBRTE_BITRATE + tics_current = rte_rdtsc(); + if (tics_current - tics_datum >= tics_per_1sec) { + /* Periodic bitrate calculation */ + for (idx_port = 0; idx_port < cnt_ports; idx_port++) + rte_stats_bitrate_calc(bitrate_data, idx_port); + tics_datum = tics_current; + } +#endif } while (! fc->stopped); } @@ -2139,6 +2166,15 @@ main(int argc, char** argv) FOREACH_PORT(port_id, ports) rte_eth_promiscuous_enable(port_id); + /* Setup bitrate stats */ +#ifdef RTE_LIBRTE_BITRATE + bitrate_data = rte_stats_bitrate_create(); + if (bitrate_data == NULL) + rte_exit(EXIT_FAILURE, "Could not allocate bitrate data.\n"); + rte_stats_bitrate_reg(bitrate_data); +#endif + + #ifdef RTE_LIBRTE_CMDLINE if (interactive == 1) { if (auto_start) { -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [PATCH v6 3/4] app/test-pmd: add support for bitrate statistics 2017-01-11 16:03 ` [dpdk-dev] [PATCH v6 3/4] app/test-pmd: add support for bitrate statistics Remy Horton @ 2017-01-12 13:32 ` Thomas Monjalon 0 siblings, 0 replies; 115+ messages in thread From: Thomas Monjalon @ 2017-01-12 13:32 UTC (permalink / raw) To: Remy Horton; +Cc: dev I do not understand clearly this library and the output from testpmd. It seems you have a need but you do not explain why it is not done in the application. Bitrate is specific to ethdev, right? Why not put it directly in testpmd first? ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v6 4/4] latencystats: added new library for latency stats 2017-01-11 16:03 ` [dpdk-dev] [PATCH v6 0/4] Expanded statistics reporting Remy Horton ` (2 preceding siblings ...) 2017-01-11 16:03 ` [dpdk-dev] [PATCH v6 3/4] app/test-pmd: add support for bitrate statistics Remy Horton @ 2017-01-11 16:03 ` Remy Horton 2017-01-12 13:41 ` Thomas Monjalon 2017-01-11 16:58 ` [dpdk-dev] [PATCH v6 0/4] Expanded statistics reporting Thomas Monjalon 2017-01-16 16:19 ` [dpdk-dev] [PATCH v7 0/6] " Remy Horton 5 siblings, 1 reply; 115+ messages in thread From: Remy Horton @ 2017-01-11 16:03 UTC (permalink / raw) To: dev; +Cc: Thomas Monjalon, Reshma Pattan Add a library designed to calculate latency statistics and report them to the application when queried. The library measures minimum, average and maximum latencies, and jitter in nano seconds. The current implementation supports global latency stats, i.e. per application stats. Added new field to mbuf struct to mark the packet arrival time on Rx. Modify testpmd code to initialize/uninitialize latency statistics calulation. Modify the dpdk-procinfo process to display the newly added metrics. Added new command line option "--metrics" to display metrics. APIs: * Added APIs to initialize and un initialize latency stats calculation. * Added API to retrieve latency stats names and values. Functionality: * The library will register ethdev Rx/Tx callbacks for each active port, queue combinations. * The library will register latency stats names with new metrics library. * Rx packets will be marked with time stamp on each sampling interval. * On Tx side, packets with time stamp will be considered for calculating the minimum, maximum, average latencies and also jitter. * Average latency is calculated using exponential weighted moving average method. * Minimum and maximum latencies will be low and high latency values observed so far. * Jitter calculation is done based on inter packet delay variation. * Measured stats are reported to the metrics library in a separate pthread. * Measured stats can be retrieved via get API of the libray (or) by calling generic get API of the new metrics library. Signed-off-by: Reshma Pattan <reshma.pattan@intel.com> Signed-off-by: Remy Horton <remy.horton@intel.com> --- MAINTAINERS | 4 + app/proc_info/main.c | 73 ++++ app/test-pmd/testpmd.c | 10 + config/common_base | 5 + doc/api/doxy-api-index.md | 1 + doc/api/doxy-api.conf | 1 + doc/guides/rel_notes/release_17_02.rst | 5 + lib/Makefile | 1 + lib/librte_latencystats/Makefile | 57 +++ lib/librte_latencystats/rte_latencystats.c | 389 +++++++++++++++++++++ lib/librte_latencystats/rte_latencystats.h | 146 ++++++++ .../rte_latencystats_version.map | 10 + lib/librte_mbuf/rte_mbuf.h | 3 + mk/rte.app.mk | 2 +- 14 files changed, 706 insertions(+), 1 deletion(-) create mode 100644 lib/librte_latencystats/Makefile create mode 100644 lib/librte_latencystats/rte_latencystats.c create mode 100644 lib/librte_latencystats/rte_latencystats.h create mode 100644 lib/librte_latencystats/rte_latencystats_version.map diff --git a/MAINTAINERS b/MAINTAINERS index 6cd9896..0a41fe5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -714,3 +714,7 @@ F: examples/tep_termination/ F: examples/vmdq/ F: examples/vmdq_dcb/ F: doc/guides/sample_app_ug/vmdq_dcb_forwarding.rst + +Latency Stats +M: Reshma Pattan <reshma.pattan@intel.com> +F: lib/librte_latencystats/ diff --git a/app/proc_info/main.c b/app/proc_info/main.c index 2c56d10..5f801a9 100644 --- a/app/proc_info/main.c +++ b/app/proc_info/main.c @@ -57,6 +57,7 @@ #include <rte_atomic.h> #include <rte_branch_prediction.h> #include <rte_string_fns.h> +#include <rte_metrics.h> /* Maximum long option length for option parsing. */ #define MAX_LONG_OPT_SZ 64 @@ -68,6 +69,8 @@ static uint32_t enabled_port_mask; static uint32_t enable_stats; /**< Enable xstats. */ static uint32_t enable_xstats; +/**< Enable metrics. */ +static uint32_t enable_metrics; /**< Enable stats reset. */ static uint32_t reset_stats; /**< Enable xstats reset. */ @@ -85,6 +88,8 @@ proc_info_usage(const char *prgname) " --stats: to display port statistics, enabled by default\n" " --xstats: to display extended port statistics, disabled by " "default\n" + " --metrics: to display derived metrics of the ports, disabled by " + "default\n" " --stats-reset: to reset port statistics\n" " --xstats-reset: to reset port extended statistics\n", prgname); @@ -127,6 +132,7 @@ proc_info_parse_args(int argc, char **argv) {"stats", 0, NULL, 0}, {"stats-reset", 0, NULL, 0}, {"xstats", 0, NULL, 0}, + {"metrics", 0, NULL, 0}, {"xstats-reset", 0, NULL, 0}, {NULL, 0, 0, 0} }; @@ -159,6 +165,10 @@ proc_info_parse_args(int argc, char **argv) else if (!strncmp(long_option[option_index].name, "xstats", MAX_LONG_OPT_SZ)) enable_xstats = 1; + else if (!strncmp(long_option[option_index].name, + "metrics", + MAX_LONG_OPT_SZ)) + enable_metrics = 1; /* Reset stats */ if (!strncmp(long_option[option_index].name, "stats-reset", MAX_LONG_OPT_SZ)) @@ -301,6 +311,63 @@ nic_xstats_clear(uint8_t port_id) printf("\n NIC extended statistics for port %d cleared\n", port_id); } +static void +metrics_display(int port_id) +{ + struct rte_metric_value *metrics; + struct rte_metric_name *names; + int len, ret; + static const char *nic_stats_border = "########################"; + + memset(&metrics, 0, sizeof(struct rte_metric_value)); + len = rte_metrics_get_names(NULL, 0); + if (len < 0) { + printf("Cannot get metrics count\n"); + return; + } + + metrics = malloc(sizeof(struct rte_metric_value) * len); + if (metrics == NULL) { + printf("Cannot allocate memory for metrics\n"); + return; + } + + names = malloc(sizeof(struct rte_metric_name) * len); + if (names == NULL) { + printf("Cannot allocate memory for metrcis names\n"); + free(metrics); + return; + } + + if (len != rte_metrics_get_names(names, len)) { + printf("Cannot get metrics names\n"); + free(metrics); + free(names); + return; + } + + if (port_id == RTE_METRICS_NONPORT) + printf("###### Non port specific metrics #########\n"); + else + printf("###### metrics for port %-2d #########\n", port_id); + printf("%s############################\n", nic_stats_border); + ret = rte_metrics_get_values(port_id, metrics, len); + if (ret < 0 || ret > len) { + printf("Cannot get metrics values\n"); + free(metrics); + free(names); + return; + } + + int i; + for (i = 0; i < len; i++) + printf("%s: %"PRIu64"\n", names[i].name, metrics[i].value); + + printf("%s############################\n", nic_stats_border); + free(metrics); + free(names); +} + int main(int argc, char **argv) { @@ -360,8 +427,14 @@ main(int argc, char **argv) nic_stats_clear(i); else if (reset_xstats) nic_xstats_clear(i); + else if (enable_metrics) + metrics_display(i); } } + /* print port independent stats */ + if (enable_metrics) + metrics_display(RTE_METRICS_NONPORT); + return 0; } diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c index a0b7430..2874ce4 100644 --- a/app/test-pmd/testpmd.c +++ b/app/test-pmd/testpmd.c @@ -83,6 +83,10 @@ #ifdef RTE_LIBRTE_BITRATE #include <rte_bitrate.h> #endif +#include <rte_metrics.h> +#ifdef RTE_LIBRTE_LATENCY_STATS +#include <rte_latencystats.h> +#endif #include "testpmd.h" @@ -2108,6 +2112,9 @@ signal_handler(int signum) /* uninitialize packet capture framework */ rte_pdump_uninit(); #endif +#ifdef RTE_LIBRTE_LATENCY_STATS + rte_latencystats_uninit(); +#endif force_quit(); /* exit with the expected status */ signal(signum, SIG_DFL); @@ -2165,6 +2172,9 @@ main(int argc, char** argv) /* set all ports to promiscuous mode by default */ FOREACH_PORT(port_id, ports) rte_eth_promiscuous_enable(port_id); +#ifdef RTE_LIBRTE_LATENCY_STATS + rte_latencystats_init(1, NULL); +#endif /* Setup bitrate stats */ #ifdef RTE_LIBRTE_BITRATE diff --git a/config/common_base b/config/common_base index decebe5..762a54c 100644 --- a/config/common_base +++ b/config/common_base @@ -603,3 +603,8 @@ CONFIG_RTE_LIBRTE_METRICS=y # Compile the bitrate statistics library # CONFIG_RTE_LIBRTE_BITRATE=y + +# +# Compile the latency statistics library +# +CONFIG_RTE_LIBRTE_LATENCY_STATS=y diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md index 5e194b0..1cacacc 100644 --- a/doc/api/doxy-api-index.md +++ b/doc/api/doxy-api-index.md @@ -152,4 +152,5 @@ There are many libraries, so their headers may be grouped by topics: [keepalive] (@ref rte_keepalive.h), [Device Metrics] (@ref rte_metrics.h), [Bitrate Statistics] (@ref rte_bitrate.h), + [Latency stats] (@ref rte_latencystats.h), [version] (@ref rte_version.h) diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf index ff15f5b..1e55da4 100644 --- a/doc/api/doxy-api.conf +++ b/doc/api/doxy-api.conf @@ -46,6 +46,7 @@ INPUT = doc/api/doxy-api-index.md \ lib/librte_jobstats \ lib/librte_kni \ lib/librte_kvargs \ + lib/librte_latencystats \ lib/librte_lpm \ lib/librte_mbuf \ lib/librte_mempool \ diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst index 70f93e1..52c7142 100644 --- a/doc/guides/rel_notes/release_17_02.rst +++ b/doc/guides/rel_notes/release_17_02.rst @@ -63,6 +63,10 @@ New Features See the :ref:`Generic flow API <Generic_flow_API>` documentation for more information. +* **Added latency stats library.** + A library that facilitates latency stats measurment of the dpdk based applications. + The library measures minimum, average, maximum latencies and also jitter + in nano seconds. Resolved Issues --------------- @@ -179,6 +183,7 @@ The libraries prepended with a plus sign were incremented in this version. librte_jobstats.so.1 librte_kni.so.2 librte_kvargs.so.1 + + librte_latencystats.so.1 librte_lpm.so.2 librte_mbuf.so.2 librte_mempool.so.2 diff --git a/lib/Makefile b/lib/Makefile index e211bc0..6fffa88 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -60,6 +60,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics DIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += librte_bitratestats +DIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += librte_latencystats ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni diff --git a/lib/librte_latencystats/Makefile b/lib/librte_latencystats/Makefile new file mode 100644 index 0000000..f744da6 --- /dev/null +++ b/lib/librte_latencystats/Makefile @@ -0,0 +1,57 @@ +# BSD LICENSE +# +# Copyright(c) 2016 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +include $(RTE_SDK)/mk/rte.vars.mk + +# library name +LIB = librte_latencystats.a + +CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3 +LDLIBS += -lm +LDLIBS += -lpthread + +EXPORT_MAP := rte_latencystats_version.map + +LIBABIVER := 1 + +# all source are stored in SRCS-y +SRCS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) := rte_latencystats.c + +# install this header file +SYMLINK-$(CONFIG_RTE_LIBRTE_LATENCY_STATS)-include := rte_latencystats.h + +# this lib depends upon: +DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_mbuf +DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_eal +DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_ether +DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_metrics + +include $(RTE_SDK)/mk/rte.lib.mk diff --git a/lib/librte_latencystats/rte_latencystats.c b/lib/librte_latencystats/rte_latencystats.c new file mode 100644 index 0000000..dcde7f6 --- /dev/null +++ b/lib/librte_latencystats/rte_latencystats.c @@ -0,0 +1,389 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <unistd.h> +#include <sys/types.h> +#include <stdbool.h> +#include <math.h> +#include <pthread.h> + +#include <rte_mbuf.h> +#include <rte_log.h> +#include <rte_cycles.h> +#include <rte_ethdev.h> +#include <rte_metrics.h> +#include <rte_memzone.h> +#include <rte_lcore.h> +#include <rte_timer.h> + +#include "rte_latencystats.h" + +/** Nano seconds per second */ +#define NS_PER_SEC 1E9 + +/** Clock cycles per nano second */ +#define CYCLES_PER_NS (rte_get_timer_hz() / NS_PER_SEC) + +/* Macros for printing using RTE_LOG */ +#define RTE_LOGTYPE_LATENCY_STATS RTE_LOGTYPE_USER1 + +static pthread_t latency_stats_thread; +static const char *MZ_RTE_LATENCY_STATS = "rte_latencystats"; +static int latency_stats_index; +static uint64_t samp_intvl; +static uint64_t timer_tsc; +static uint64_t prev_tsc; + +static struct rte_latency_stats { + float min_latency; /**< Minimum latency in nano seconds */ + float avg_latency; /**< Average latency in nano seconds */ + float max_latency; /**< Maximum latency in nano seconds */ + float jitter; /** Latency variation */ +} *glob_stats; + +static struct rxtx_cbs { + struct rte_eth_rxtx_callback *cb; +} rx_cbs[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT], + tx_cbs[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT]; + +struct latency_stats_nameoff { + char name[RTE_ETH_XSTATS_NAME_SIZE]; + unsigned int offset; +}; + +static const struct latency_stats_nameoff lat_stats_strings[] = { + {"min_latency_ns", offsetof(struct rte_latency_stats, min_latency)}, + {"avg_latency_ns", offsetof(struct rte_latency_stats, avg_latency)}, + {"max_latency_ns", offsetof(struct rte_latency_stats, max_latency)}, + {"jitter_ns", offsetof(struct rte_latency_stats, jitter)}, +}; + +#define NUM_LATENCY_STATS (sizeof(lat_stats_strings) / \ + sizeof(lat_stats_strings[0])) + +static __attribute__((noreturn)) void * +report_latency_stats(__rte_unused void *arg) +{ + for (;;) { + unsigned int i; + float *stats_ptr = NULL; + uint64_t values[NUM_LATENCY_STATS] = {0}; + int ret; + + for (i = 0; i < NUM_LATENCY_STATS; i++) { + stats_ptr = RTE_PTR_ADD(glob_stats, + lat_stats_strings[i].offset); + values[i] = (uint64_t)floor((*stats_ptr)/ + CYCLES_PER_NS); + } + + ret = rte_metrics_update_metrics(RTE_METRICS_NONPORT, + latency_stats_index, + values, NUM_LATENCY_STATS); + if (ret < 0) + RTE_LOG(INFO, LATENCY_STATS, + "Failed to push the stats\n"); + } +} + +static void +rte_latencystats_fill_values(struct rte_metric_value *values) +{ + unsigned int i; + float *stats_ptr = NULL; + + for (i = 0; i < NUM_LATENCY_STATS; i++) { + stats_ptr = RTE_PTR_ADD(glob_stats, + lat_stats_strings[i].offset); + values[i].key = i; + values[i].value = (uint64_t)floor((*stats_ptr)/ + CYCLES_PER_NS); + } +} + +static uint16_t +add_time_stamps(uint8_t pid __rte_unused, + uint16_t qid __rte_unused, + struct rte_mbuf **pkts, + uint16_t nb_pkts, + uint16_t max_pkts __rte_unused, + void *user_cb __rte_unused) +{ + unsigned int i; + uint64_t diff_tsc, now; + + /* + * For every sample interval, + * time stamp is marked on one received packet. + */ + now = rte_rdtsc(); + for (i = 0; i < nb_pkts; i++) { + diff_tsc = now - prev_tsc; + timer_tsc += diff_tsc; + if (timer_tsc >= samp_intvl) { + /* + * TBD: Mark the timestamp only + * if not already marked by the + * hardware or the PMD. + */ + pkts[i]->timestamp = now; + timer_tsc = 0; + } + prev_tsc = now; + now = rte_rdtsc(); + } + + return nb_pkts; +} + +static uint16_t +calc_latency(uint8_t pid __rte_unused, + uint16_t qid __rte_unused, + struct rte_mbuf **pkts, + uint16_t nb_pkts, + void *_ __rte_unused) +{ + unsigned int i, cnt = 0; + uint64_t now; + float latency[nb_pkts]; + static float prev_latency; + /* + * Alpha represents degree of weighting decrease in EWMA, + * a constant smoothing factor between 0 and 1. The value + * is used below for measuring average latency. + */ + const float alpha = 0.2; + + now = rte_rdtsc(); + for (i = 0; i < nb_pkts; i++) { + if (pkts[i]->timestamp) + latency[cnt++] = now - pkts[i]->timestamp; + } + + for (i = 0; i < cnt; i++) { + /* + * The jitter is calculated as statistical mean of interpacket + * delay variation. The "jitter estimate" is computed by taking + * the absolute values of the ipdv sequence and applying an + * exponential filter with parameter 1/16 to generate the + * estimate. i.e J=J+(|D(i-1,i)|-J)/16. Where J is jitter, + * D(i-1,i) is difference in latency of two consecutive packets + * i-1 and i. + * Reference: Calculated as per RFC 5481, sec 4.1, + * RFC 3393 sec 4.5, RFC 1889 sec. + */ + glob_stats->jitter += (abs(prev_latency - latency[i]) + - glob_stats->jitter)/16; + if (glob_stats->min_latency == 0) + glob_stats->min_latency = latency[i]; + else if (latency[i] < glob_stats->min_latency) + glob_stats->min_latency = latency[i]; + else if (latency[i] > glob_stats->max_latency) + glob_stats->max_latency = latency[i]; + /* + * The average latency is measured using exponential moving + * average, i.e. using EWMA + * https://en.wikipedia.org/wiki/Moving_average + */ + glob_stats->avg_latency += + alpha * (latency[i] - glob_stats->avg_latency); + prev_latency = latency[i]; + } + + return nb_pkts; +} + +int +rte_latencystats_init(uint64_t samp_intvl, + rte_latency_stats_flow_type_fn user_cb) +{ + unsigned int i; + uint8_t pid; + uint16_t qid; + struct rxtx_cbs *cbs = NULL; + const uint8_t nb_ports = rte_eth_dev_count(); + const char *ptr_strings[NUM_LATENCY_STATS] = {0}; + const struct rte_memzone *mz = NULL; + const unsigned int flags = 0; + + /** Allocate stats in shared memory fo muliti process support */ + mz = rte_memzone_reserve(MZ_RTE_LATENCY_STATS, sizeof(*glob_stats), + rte_socket_id(), flags); + if (mz == NULL) { + RTE_LOG(ERR, LATENCY_STATS, "Cannot reserve memory: %s:%d\n", + __func__, __LINE__); + return -ENOMEM; + } + + glob_stats = mz->addr; + samp_intvl *= CYCLES_PER_NS; + + /** Register latency stats with stats library */ + for (i = 0; i < NUM_LATENCY_STATS; i++) + ptr_strings[i] = lat_stats_strings[i].name; + + latency_stats_index = rte_metrics_reg_metrics(ptr_strings, + NUM_LATENCY_STATS); + if (latency_stats_index < 0) { + RTE_LOG(DEBUG, LATENCY_STATS, + "Failed to register latency stats names\n"); + return -1; + } + + /** Register Rx/Tx callbacks */ + for (pid = 0; pid < nb_ports; pid++) { + struct rte_eth_dev_info dev_info; + rte_eth_dev_info_get(pid, &dev_info); + for (qid = 0; qid < dev_info.nb_rx_queues; qid++) { + cbs = &rx_cbs[pid][qid]; + cbs->cb = rte_eth_add_first_rx_callback(pid, qid, + add_time_stamps, user_cb); + if (!cbs->cb) + RTE_LOG(INFO, LATENCY_STATS, "Failed to " + "register Rx callback for pid=%d, " + "qid=%d\n", pid, qid); + } + for (qid = 0; qid < dev_info.nb_tx_queues; qid++) { + cbs = &tx_cbs[pid][qid]; + cbs->cb = rte_eth_add_tx_callback(pid, qid, + calc_latency, user_cb); + if (!cbs->cb) + RTE_LOG(INFO, LATENCY_STATS, "Failed to " + "register Tx callback for pid=%d, " + "qid=%d\n", pid, qid); + } + } + + int ret = 0; + char thread_name[RTE_MAX_THREAD_NAME_LEN]; + + /** Create the host thread to update latency stats to stats library */ + ret = pthread_create(&latency_stats_thread, NULL, report_latency_stats, + NULL); + if (ret != 0) { + RTE_LOG(ERR, LATENCY_STATS, + "Failed to create the latency stats thread:%s, %s:%d\n", + strerror(errno), __func__, __LINE__); + return -1; + } + /** Set thread_name for aid in debugging */ + snprintf(thread_name, RTE_MAX_THREAD_NAME_LEN, "latency-stats-thread"); + ret = rte_thread_setname(latency_stats_thread, thread_name); + if (ret != 0) + RTE_LOG(DEBUG, LATENCY_STATS, + "Failed to set thread name for latency stats handling\n"); + + return 0; +} + +int +rte_latencystats_uninit(void) +{ + uint8_t pid; + uint16_t qid; + int ret = 0; + struct rxtx_cbs *cbs = NULL; + const uint8_t nb_ports = rte_eth_dev_count(); + + /** De register Rx/Tx callbacks */ + for (pid = 0; pid < nb_ports; pid++) { + struct rte_eth_dev_info dev_info; + rte_eth_dev_info_get(pid, &dev_info); + for (qid = 0; qid < dev_info.nb_rx_queues; qid++) { + cbs = &rx_cbs[pid][qid]; + ret = rte_eth_remove_rx_callback(pid, qid, cbs->cb); + if (ret) + RTE_LOG(INFO, LATENCY_STATS, "failed to " + "remove Rx callback for pid=%d, " + "qid=%d\n", pid, qid); + } + for (qid = 0; qid < dev_info.nb_tx_queues; qid++) { + cbs = &tx_cbs[pid][qid]; + ret = rte_eth_remove_tx_callback(pid, qid, cbs->cb); + if (ret) + RTE_LOG(INFO, LATENCY_STATS, "failed to " + "remove Tx callback for pid=%d, " + "qid=%d\n", pid, qid); + } + } + + /** Cancel the thread */ + ret = pthread_cancel(latency_stats_thread); + if (ret != 0) { + RTE_LOG(ERR, LATENCY_STATS, + "Failed to cancel latency stats update thread:" + "%s,%s:%d\n", + strerror(errno), __func__, __LINE__); + return -1; + } + + return 0; +} + +int +rte_latencystats_get_names(struct rte_metric_name *names, uint16_t size) +{ + unsigned int i; + + if (names == NULL || size < NUM_LATENCY_STATS) + return NUM_LATENCY_STATS; + + for (i = 0; i < NUM_LATENCY_STATS; i++) + snprintf(names[i].name, sizeof(names[i].name), + "%s", lat_stats_strings[i].name); + + return NUM_LATENCY_STATS; +} + +int +rte_latencystats_get(struct rte_metric_value *values, uint16_t size) +{ + if (size < NUM_LATENCY_STATS || values == NULL) + return NUM_LATENCY_STATS; + + if (rte_eal_process_type() == RTE_PROC_SECONDARY) { + const struct rte_memzone *mz; + mz = rte_memzone_lookup(MZ_RTE_LATENCY_STATS); + if (mz == NULL) { + RTE_LOG(ERR, LATENCY_STATS, + "Latency stats memzone not found\n"); + return -ENOMEM; + } + glob_stats = mz->addr; + } + + /* Retrieve latency stats */ + rte_latencystats_fill_values(values); + + return NUM_LATENCY_STATS; +} diff --git a/lib/librte_latencystats/rte_latencystats.h b/lib/librte_latencystats/rte_latencystats.h new file mode 100644 index 0000000..405b878 --- /dev/null +++ b/lib/librte_latencystats/rte_latencystats.h @@ -0,0 +1,146 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _RTE_LATENCYSTATS_H_ +#define _RTE_LATENCYSTATS_H_ + +/** + * @file + * RTE latency stats + * + * library to provide application and flow based latency stats. + */ + +#include <rte_metrics.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Note: This function pointer is for future flow based latency stats + * implementation. + * + * Function type used for identifting flow types of a Rx packet. + * + * The callback function is called on Rx for each packet. + * This function is used for flow based latency calculations. + * + * @param pkt + * Packet that has to be identified with its flow types. + * @param user_param + * The arbitrary user parameter passed in by the application when + * the callback was originally configured. + * @return + * The flow_mask, representing the multiple flow types of a packet. + */ +typedef uint16_t (*rte_latency_stats_flow_type_fn)(struct rte_mbuf *pkt, + void *user_param); + +/** + * Registers Rx/Tx callbacks for each active port, queue. + * + * @param samp_intvl + * Sampling time period in nano seconds, at which packet + * should be marked with time stamp. + * @param user_cb + * Note: This param is for future flow based latency stats + * implementation. + * User callback to be called to get flow types of a packet. + * Used for flow based latency calculation. + * If the value is NULL, global stats will be calculated, + * else flow based latency stats will be calculated. + * For now just pass on the NULL value to this param. + * @return + * -1 : On error + * -ENOMEM: On error + * 0 : On success + */ +int rte_latencystats_init(uint64_t samp_intvl, + rte_latency_stats_flow_type_fn user_cb); + +/** + * Removes registered Rx/Tx callbacks for each active port, queue. + * + * @return + * -1: On error + * 0: On success + */ +int rte_latencystats_uninit(void); + +/** + * Retrieve names of latency statistics + * + * @param names + * Block of memory to insert names into. Must be at least size in capacity. + * If set to NULL, function returns required capacity. + * @param size + * Capacity of latency stats names (number of names). + * @return + * - positive value lower or equal to size: success. The return value + * is the number of entries filled in the stats table. + * - positive value higher than size: error, the given statistics table + * is too small. The return value corresponds to the size that should + * be given to succeed. The entries in the table are not valid and + * shall not be used by the caller. + */ +int rte_latencystats_get_names(struct rte_metric_name *names, + uint16_t size); + +/** + * Retrieve latency statistics. + * + * @param values + * A pointer to a table of structure of type *rte_metric_value* + * to be filled with latency statistics ids and values. + * This parameter can be set to NULL if size is 0. + * @param size + * The size of the stats table, which should be large enough to store + * all the latency stats. + * @return + * - positive value lower or equal to size: success. The return value + * is the number of entries filled in the stats table. + * - positive value higher than size: error, the given statistics table + * is too small. The return value corresponds to the size that should + * be given to succeed. The entries in the table are not valid and + * shall not be used by the caller. + * -ENOMEM: On failure. + */ +int rte_latencystats_get(struct rte_metric_value *values, + uint16_t size); + +#ifdef __cplusplus +} +#endif + +#endif /* _RTE_LATENCYSTATS_H_ */ diff --git a/lib/librte_latencystats/rte_latencystats_version.map b/lib/librte_latencystats/rte_latencystats_version.map new file mode 100644 index 0000000..502018e --- /dev/null +++ b/lib/librte_latencystats/rte_latencystats_version.map @@ -0,0 +1,10 @@ +DPDK_17.02 { + global: + + rte_latencystats_get; + rte_latencystats_get_names; + rte_latencystats_init; + rte_latencystats_uninit; + + local: *; +}; diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h index 4476d75..df85d48 100644 --- a/lib/librte_mbuf/rte_mbuf.h +++ b/lib/librte_mbuf/rte_mbuf.h @@ -506,6 +506,9 @@ struct rte_mbuf { /** Timesync flags for use with IEEE1588. */ uint16_t timesync; + + /** Timestamp for measuring latency. */ + uint64_t timestamp; } __rte_cache_aligned; /** diff --git a/mk/rte.app.mk b/mk/rte.app.mk index 6aac5ac..1d36fad 100644 --- a/mk/rte.app.mk +++ b/mk/rte.app.mk @@ -100,7 +100,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE) += -lrte_cmdline _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE) += -lrte_cfgfile _LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS) += -lrte_metrics _LDLIBS-$(CONFIG_RTE_LIBRTE_BITRATE) += -lrte_bitratestats - +_LDLIBS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += -lrte_latencystats _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += -lrte_pmd_bond _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += -lrte_pmd_xenvirt -lxenstore -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [PATCH v6 4/4] latencystats: added new library for latency stats 2017-01-11 16:03 ` [dpdk-dev] [PATCH v6 4/4] latencystats: added new library for latency stats Remy Horton @ 2017-01-12 13:41 ` Thomas Monjalon 2017-01-12 14:44 ` Remy Horton 2017-01-13 9:45 ` Mcnamara, John 0 siblings, 2 replies; 115+ messages in thread From: Thomas Monjalon @ 2017-01-12 13:41 UTC (permalink / raw) To: Remy Horton, Reshma Pattan; +Cc: dev, olivier.matz 2017-01-12 00:03, Remy Horton: > Add a library designed to calculate latency statistics and report them > to the application when queried. The library measures minimum, average and > maximum latencies, and jitter in nano seconds. The current implementation > supports global latency stats, i.e. per application stats. Is it specific to ethdev ports? > Added new field to mbuf struct to mark the packet arrival time on Rx. There was another patch adding a timestamp in mbuf: http://dpdk.org/ml/archives/dev/2016-October/048809.html > Modify testpmd code to initialize/uninitialize latency statistics > calulation. > > Modify the dpdk-procinfo process to display the newly added metrics. > Added new command line option "--metrics" to display metrics. It should be a separate patch. > APIs: > > * Added APIs to initialize and un initialize latency stats > calculation. > * Added API to retrieve latency stats names and values. Why bitrate and latencies are separate libs? ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [PATCH v6 4/4] latencystats: added new library for latency stats 2017-01-12 13:41 ` Thomas Monjalon @ 2017-01-12 14:44 ` Remy Horton 2017-01-13 9:45 ` Mcnamara, John 1 sibling, 0 replies; 115+ messages in thread From: Remy Horton @ 2017-01-12 14:44 UTC (permalink / raw) To: Thomas Monjalon, Reshma Pattan; +Cc: dev, olivier.matz On 12/01/2017 13:41, Thomas Monjalon wrote: > 2017-01-12 00:03, Remy Horton: >> Add a library designed to calculate latency statistics and report them >> to the application when queried. The library measures minimum, average and >> maximum latencies, and jitter in nano seconds. The current implementation >> supports global latency stats, i.e. per application stats. > > Is it specific to ethdev ports? No (or at least not at the moment). >> Added new field to mbuf struct to mark the packet arrival time on Rx. > > There was another patch adding a timestamp in mbuf: > http://dpdk.org/ml/archives/dev/2016-October/048809.html Will look into it. Since time is tight will have internal discussion whether latency will make it into 17.02.. >> APIs: >> >> * Added APIs to initialize and un initialize latency stats >> calculation. >> * Added API to retrieve latency stats names and values. > > Why bitrate and latencies are separate libs? They were developed independently by different people in response to seperate requirements. Reshma went on extended leave, so I took over the latency patch at the last moment when development was complete. Aside from rebase-related fixups and one printf change it is the last version of her seperate patch included verbatim. ..Remy ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [PATCH v6 4/4] latencystats: added new library for latency stats 2017-01-12 13:41 ` Thomas Monjalon 2017-01-12 14:44 ` Remy Horton @ 2017-01-13 9:45 ` Mcnamara, John 2017-01-13 9:53 ` Thomas Monjalon 1 sibling, 1 reply; 115+ messages in thread From: Mcnamara, John @ 2017-01-13 9:45 UTC (permalink / raw) To: Thomas Monjalon, Horton, Remy, Pattan, Reshma; +Cc: dev, olivier.matz > -----Original Message----- > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Thomas Monjalon > Sent: Thursday, January 12, 2017 1:41 PM > To: Horton, Remy <remy.horton@intel.com>; Pattan, Reshma > <reshma.pattan@intel.com> > Cc: dev@dpdk.org; olivier.matz@6wind.com > Subject: Re: [dpdk-dev] [PATCH v6 4/4] latencystats: added new library for > latency stats > > 2017-01-12 00:03, Remy Horton: > > Add a library designed to calculate latency statistics and report them > > to the application when queried. The library measures minimum, average > > and maximum latencies, and jitter in nano seconds. The current > > implementation supports global latency stats, i.e. per application > stats. > > Is it specific to ethdev ports? > > > Added new field to mbuf struct to mark the packet arrival time on Rx. > > There was another patch adding a timestamp in mbuf: > http://dpdk.org/ml/archives/dev/2016-October/048809.html Hi Thomas, Is that an issue? The other patch adds the same field for more or less the same purpose. If the other patch goes in we can rework this patch or if this patch goes in the other one won't be required. John ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [PATCH v6 4/4] latencystats: added new library for latency stats 2017-01-13 9:45 ` Mcnamara, John @ 2017-01-13 9:53 ` Thomas Monjalon 2017-01-16 16:18 ` Mcnamara, John 0 siblings, 1 reply; 115+ messages in thread From: Thomas Monjalon @ 2017-01-13 9:53 UTC (permalink / raw) To: Mcnamara, John, Horton, Remy; +Cc: Pattan, Reshma, dev, olivier.matz 2017-01-13 09:45, Mcnamara, John: > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Thomas Monjalon > > 2017-01-12 00:03, Remy Horton: > > > Add a library designed to calculate latency statistics and report them > > > to the application when queried. The library measures minimum, average > > > and maximum latencies, and jitter in nano seconds. The current > > > implementation supports global latency stats, i.e. per application > > stats. > > > > Is it specific to ethdev ports? > > > > > Added new field to mbuf struct to mark the packet arrival time on Rx. > > > > There was another patch adding a timestamp in mbuf: > > http://dpdk.org/ml/archives/dev/2016-October/048809.html > > Hi Thomas, > > Is that an issue? The other patch adds the same field for more or less the same purpose. > If the other patch goes in we can rework this patch or if this patch goes in the > other one won't be required. Yes The only issue is that it is not yet accepted or merged. I think Olivier was considering it in a more global mbuf rework. ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [PATCH v6 4/4] latencystats: added new library for latency stats 2017-01-13 9:53 ` Thomas Monjalon @ 2017-01-16 16:18 ` Mcnamara, John 0 siblings, 0 replies; 115+ messages in thread From: Mcnamara, John @ 2017-01-16 16:18 UTC (permalink / raw) To: Thomas Monjalon, Horton, Remy; +Cc: Pattan, Reshma, dev, olivier.matz > -----Original Message----- > From: Thomas Monjalon [mailto:thomas.monjalon@6wind.com] > Sent: Friday, January 13, 2017 9:54 AM > To: Mcnamara, John <john.mcnamara@intel.com>; Horton, Remy > <remy.horton@intel.com> > Cc: Pattan, Reshma <reshma.pattan@intel.com>; dev@dpdk.org; > olivier.matz@6wind.com > Subject: Re: [dpdk-dev] [PATCH v6 4/4] latencystats: added new library for > latency stats > > ... > > > > Is that an issue? The other patch adds the same field for more or less > the same purpose. > > If the other patch goes in we can rework this patch or if this patch > > goes in the other one won't be required. > > Yes > The only issue is that it is not yet accepted or merged. > I think Olivier was considering it in a more global mbuf rework. Hi, I think we should put the timestamp into this release since more than one developer/feature is looking for it. If Olivier does the rework in the next release he can move it or leave it in the current position. John ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [PATCH v6 0/4] Expanded statistics reporting 2017-01-11 16:03 ` [dpdk-dev] [PATCH v6 0/4] Expanded statistics reporting Remy Horton ` (3 preceding siblings ...) 2017-01-11 16:03 ` [dpdk-dev] [PATCH v6 4/4] latencystats: added new library for latency stats Remy Horton @ 2017-01-11 16:58 ` Thomas Monjalon 2017-01-16 16:19 ` [dpdk-dev] [PATCH v7 0/6] " Remy Horton 5 siblings, 0 replies; 115+ messages in thread From: Thomas Monjalon @ 2017-01-11 16:58 UTC (permalink / raw) To: Remy Horton; +Cc: dev 2017-01-12 00:03, Remy Horton: > Due to merge issues Reshma's latency statistics, which depends > on the reporting library, has been merged into this patchset. You losed Reshma authorship. It can be fixed with "git commit --amend --author" ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v7 0/6] Expanded statistics reporting 2017-01-11 16:03 ` [dpdk-dev] [PATCH v6 0/4] Expanded statistics reporting Remy Horton ` (4 preceding siblings ...) 2017-01-11 16:58 ` [dpdk-dev] [PATCH v6 0/4] Expanded statistics reporting Thomas Monjalon @ 2017-01-16 16:19 ` Remy Horton 2017-01-16 16:19 ` [dpdk-dev] [PATCH v7 1/6] lib: add information metrics library Remy Horton ` (6 more replies) 5 siblings, 7 replies; 115+ messages in thread From: Remy Horton @ 2017-01-16 16:19 UTC (permalink / raw) To: dev; +Cc: Thomas Monjalon This patchset extends statistics reporting to include peak and average data-rate metrics. It comes in two parts: a statistics reporting library, and a bitrate calculation library that uses it. This structure is intended to seperate statistic reporting from ethdev and allow more flexible metric registration. Due to merge issues Reshma's latency statistics, which depends on the reporting library, has been merged into this patchset. -- v7 changes: * RTE_METRICS_NONPORT renamed to RTE_METRICS_GLOBAL * Multiple changes to rte_metrics.h doxygen documentation * Split apart latency patch into lib, test-pmd, & proc_info parts * Reordered patches by functionality * Insufficent capacity return value changed from -ERANGE to actual size * Cache alignment in bitrate library * Tightened up const usage to avoid STATIC_CONST_CHAR_ARRAY warning * Reshma reinstated as author for (now split) latency patch * Rebase to master v6 changes: * Metrics display now has "Non port specific" rather than "port -1" * Fixed sign issue in EWMA delta calculation * Rebased to master v5 changes: * Updated Shared Library Versions in release notes * Merged in Reshma's latencystats library v4 changes: * References to 16.11 changed to 17.02 * Fetching of non-port values was broken * Added sanity checks to value fetching * rte_stat_value renamed to rte_metric_value * Corrected doxygen descriptions * Added MAINTAINERS entries * Added #ifdef directives to bitrate code in test-pmd v3 changes: * Marked rte_stats_bitrate_s as internal * Minor integer roundoff correction * Coding style corrections * Removed spurious object allocation * Changes to rte_metrics.[ch] moved from Patch 2/3 to 1/3. * Reintroduced non-port values (RTE_METRICS_NONPORT) * Added spinlocks to metric library * Removed spurious test registration/update * Added release notes entries v2 changes: * Uses a new metrics library rather than being part of ethdev Remy Horton (3): lib: add information metrics library lib: add bitrate statistics library app/test-pmd: add bitrate statistics calculation Reshma Pattan (3): app/proc_info: add metrics displaying lib: added new library for latency stats app/test-pmd: add latency statistics calculation MAINTAINERS | 13 + app/proc_info/main.c | 73 ++++ app/test-pmd/testpmd.c | 46 +++ config/common_base | 15 + doc/api/doxy-api-index.md | 3 + doc/api/doxy-api.conf | 3 + doc/guides/rel_notes/release_17_02.rst | 18 + lib/Makefile | 3 + lib/librte_bitratestats/Makefile | 53 +++ lib/librte_bitratestats/rte_bitrate.c | 132 +++++++ lib/librte_bitratestats/rte_bitrate.h | 80 +++++ .../rte_bitratestats_version.map | 9 + lib/librte_latencystats/Makefile | 57 +++ lib/librte_latencystats/rte_latencystats.c | 389 +++++++++++++++++++++ lib/librte_latencystats/rte_latencystats.h | 146 ++++++++ .../rte_latencystats_version.map | 10 + lib/librte_mbuf/rte_mbuf.h | 3 + lib/librte_metrics/Makefile | 51 +++ lib/librte_metrics/rte_metrics.c | 310 ++++++++++++++++ lib/librte_metrics/rte_metrics.h | 223 ++++++++++++ lib/librte_metrics/rte_metrics_version.map | 13 + mk/rte.app.mk | 3 + 22 files changed, 1653 insertions(+) create mode 100644 lib/librte_bitratestats/Makefile create mode 100644 lib/librte_bitratestats/rte_bitrate.c create mode 100644 lib/librte_bitratestats/rte_bitrate.h create mode 100644 lib/librte_bitratestats/rte_bitratestats_version.map create mode 100644 lib/librte_latencystats/Makefile create mode 100644 lib/librte_latencystats/rte_latencystats.c create mode 100644 lib/librte_latencystats/rte_latencystats.h create mode 100644 lib/librte_latencystats/rte_latencystats_version.map create mode 100644 lib/librte_metrics/Makefile create mode 100644 lib/librte_metrics/rte_metrics.c create mode 100644 lib/librte_metrics/rte_metrics.h create mode 100644 lib/librte_metrics/rte_metrics_version.map -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v7 1/6] lib: add information metrics library 2017-01-16 16:19 ` [dpdk-dev] [PATCH v7 0/6] " Remy Horton @ 2017-01-16 16:19 ` Remy Horton 2017-01-17 11:01 ` Van Haaren, Harry 2017-01-16 16:19 ` [dpdk-dev] [PATCH v7 2/6] app/proc_info: add metrics displaying Remy Horton ` (5 subsequent siblings) 6 siblings, 1 reply; 115+ messages in thread From: Remy Horton @ 2017-01-16 16:19 UTC (permalink / raw) To: dev; +Cc: Thomas Monjalon This patch adds a new information metric library that allows other modules to register named metrics and update their values. It is intended to be independent of ethdev, rather than mixing ethdev and non-ethdev information in xstats. Signed-off-by: Remy Horton <remy.horton@intel.com> --- MAINTAINERS | 5 + config/common_base | 5 + doc/api/doxy-api-index.md | 1 + doc/api/doxy-api.conf | 1 + doc/guides/rel_notes/release_17_02.rst | 8 + lib/Makefile | 1 + lib/librte_metrics/Makefile | 51 +++++ lib/librte_metrics/rte_metrics.c | 310 +++++++++++++++++++++++++++++ lib/librte_metrics/rte_metrics.h | 223 +++++++++++++++++++++ lib/librte_metrics/rte_metrics_version.map | 13 ++ mk/rte.app.mk | 2 + 11 files changed, 620 insertions(+) create mode 100644 lib/librte_metrics/Makefile create mode 100644 lib/librte_metrics/rte_metrics.c create mode 100644 lib/librte_metrics/rte_metrics.h create mode 100644 lib/librte_metrics/rte_metrics_version.map diff --git a/MAINTAINERS b/MAINTAINERS index 9645c9b..4a19497 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -596,6 +596,11 @@ F: lib/librte_jobstats/ F: examples/l2fwd-jobstats/ F: doc/guides/sample_app_ug/l2_forward_job_stats.rst +Metrics +M: Remy Horton <remy.horton@intel.com> +F: lib/librte_metrics/ +F: doc/guides/sample_app_ug/keep_alive.rst + Test Applications ----------------- diff --git a/config/common_base b/config/common_base index 8e9dcfa..0eb3866 100644 --- a/config/common_base +++ b/config/common_base @@ -593,3 +593,8 @@ CONFIG_RTE_APP_TEST_RESOURCE_TAR=n CONFIG_RTE_TEST_PMD=y CONFIG_RTE_TEST_PMD_RECORD_CORE_CYCLES=n CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n + +# +# Compile the device metrics library +# +CONFIG_RTE_LIBRTE_METRICS=y diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md index 72d59b2..94f0f69 100644 --- a/doc/api/doxy-api-index.md +++ b/doc/api/doxy-api-index.md @@ -150,4 +150,5 @@ There are many libraries, so their headers may be grouped by topics: [common] (@ref rte_common.h), [ABI compat] (@ref rte_compat.h), [keepalive] (@ref rte_keepalive.h), + [Device Metrics] (@ref rte_metrics.h), [version] (@ref rte_version.h) diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf index b340fcf..194b670 100644 --- a/doc/api/doxy-api.conf +++ b/doc/api/doxy-api.conf @@ -50,6 +50,7 @@ INPUT = doc/api/doxy-api-index.md \ lib/librte_mbuf \ lib/librte_mempool \ lib/librte_meter \ + lib/librte_metrics \ lib/librte_net \ lib/librte_pdump \ lib/librte_pipeline \ diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst index d445d64..4fca29b 100644 --- a/doc/guides/rel_notes/release_17_02.rst +++ b/doc/guides/rel_notes/release_17_02.rst @@ -34,6 +34,12 @@ New Features Refer to the previous release notes for examples. + * **Added information metric library.** + + A library that allows information metrics to be added and update. It is + intended to provide a reporting mechanism that is independent of the + ethdev library. + This section is a comment. do not overwrite or remove it. Also, make sure to start the actual text at the margin. ========================================================= @@ -161,6 +167,7 @@ The libraries prepended with a plus sign were incremented in this version. .. code-block:: diff librte_acl.so.2 + + librte_bitratestats.so.1 librte_cfgfile.so.2 librte_cmdline.so.2 librte_cryptodev.so.2 @@ -176,6 +183,7 @@ The libraries prepended with a plus sign were incremented in this version. librte_mbuf.so.2 librte_mempool.so.2 librte_meter.so.1 + + librte_metrics.so.1 librte_net.so.1 librte_pdump.so.1 librte_pipeline.so.3 diff --git a/lib/Makefile b/lib/Makefile index 990f23a..5d85dcf 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -58,6 +58,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_TABLE) += librte_table DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += librte_pipeline DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump +DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni diff --git a/lib/librte_metrics/Makefile b/lib/librte_metrics/Makefile new file mode 100644 index 0000000..8d6e23a --- /dev/null +++ b/lib/librte_metrics/Makefile @@ -0,0 +1,51 @@ +# BSD LICENSE +# +# Copyright(c) 2016 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +include $(RTE_SDK)/mk/rte.vars.mk + +# library name +LIB = librte_metrics.a + +CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) + +EXPORT_MAP := rte_metrics_version.map + +LIBABIVER := 1 + +# all source are stored in SRCS-y +SRCS-$(CONFIG_RTE_LIBRTE_METRICS) := rte_metrics.c + +# Install header file +SYMLINK-$(CONFIG_RTE_LIBRTE_METRICS)-include += rte_metrics.h + +DEPDIRS-$(CONFIG_RTE_LIBRTE_METRICS) += lib/librte_eal + +include $(RTE_SDK)/mk/rte.lib.mk diff --git a/lib/librte_metrics/rte_metrics.c b/lib/librte_metrics/rte_metrics.c new file mode 100644 index 0000000..5072f4d --- /dev/null +++ b/lib/librte_metrics/rte_metrics.c @@ -0,0 +1,310 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <string.h> +#include <sys/queue.h> + +#include <rte_common.h> +#include <rte_malloc.h> +#include <rte_metrics.h> +#include <rte_lcore.h> +#include <rte_memzone.h> +#include <rte_spinlock.h> + +#define RTE_METRICS_MAX_METRICS 256 +#define RTE_METRICS_MEMZONE_NAME "RTE_METRICS" + +/** + * Internal stats metadata and value entry. + * + * @internal + * @param name + * Name of metric + * @param value + * Current value for metric + * @param idx_next_set + * Index of next root element (zero for none) + * @param idx_next_metric + * Index of next metric in set (zero for none) + * + * Only the root of each set needs idx_next_set but since it has to be + * assumed that number of sets could equal total number of metrics, + * having a separate set metadata table doesn't save any memory. + */ +struct rte_metrics_meta_s { + char name[RTE_METRICS_MAX_NAME_LEN]; + uint64_t value[RTE_MAX_ETHPORTS]; + uint64_t nonport_value; + uint16_t idx_next_set; + uint16_t idx_next_stat; +}; + +/** + * Internal stats info structure. + * + * @internal + * @param idx_last_set + * Index of last metadata entry with valid data. This value is + * not valid if cnt_stats is zero. + * @param cnt_stats + * Number of metrics. + * @param metadata + * Stat data memory block. + * + * Offsets into metadata are used instead of pointers because ASLR + * means that having the same physical addresses in different + * processes is not guaranteed. + */ +struct rte_metrics_data_s { + uint16_t idx_last_set; + uint16_t cnt_stats; + struct rte_metrics_meta_s metadata[RTE_METRICS_MAX_METRICS]; + rte_spinlock_t lock; +}; + +void +rte_metrics_init(void) +{ + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + + if (rte_eal_process_type() != RTE_PROC_PRIMARY) + return; + + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); + if (memzone != NULL) + return; + memzone = rte_memzone_reserve(RTE_METRICS_MEMZONE_NAME, + sizeof(struct rte_metrics_data_s), rte_socket_id(), 0); + if (memzone == NULL) + rte_exit(EXIT_FAILURE, "Unable to allocate stats memzone\n"); + stats = memzone->addr; + memset(stats, 0, sizeof(struct rte_metrics_data_s)); + rte_spinlock_init(&stats->lock); +} + +int +rte_metrics_reg_metric(const char *name) +{ + const char * const list_names[] = {name}; + + return rte_metrics_reg_metrics(list_names, 1); +} + +int +rte_metrics_reg_metrics(const char * const *names, uint16_t cnt_names) +{ + struct rte_metrics_meta_s *entry; + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + uint16_t idx_name; + uint16_t idx_base; + + /* Some sanity checks */ + if (cnt_names < 1 || names == NULL) + return -EINVAL; + + rte_metrics_init(); + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); + if (memzone == NULL) + return -EIO; + stats = memzone->addr; + + if (stats->cnt_stats + cnt_names >= RTE_METRICS_MAX_METRICS) + return -ENOMEM; + + rte_spinlock_lock(&stats->lock); + + /* Overwritten later if this is actually first set.. */ + stats->metadata[stats->idx_last_set].idx_next_set = stats->cnt_stats; + + stats->idx_last_set = idx_base = stats->cnt_stats; + + for (idx_name = 0; idx_name < cnt_names; idx_name++) { + entry = &stats->metadata[idx_name + stats->cnt_stats]; + strncpy(entry->name, names[idx_name], + RTE_METRICS_MAX_NAME_LEN); + memset(entry->value, 0, sizeof(entry->value)); + entry->idx_next_stat = idx_name + stats->cnt_stats + 1; + } + entry->idx_next_stat = 0; + entry->idx_next_set = 0; + stats->cnt_stats += cnt_names; + + rte_spinlock_unlock(&stats->lock); + + return idx_base; +} + +int +rte_metrics_update_metric(int port_id, uint16_t key, const uint64_t value) +{ + return rte_metrics_update_metrics(port_id, key, &value, 1); +} + +int +rte_metrics_update_metrics(int port_id, + uint16_t key, + const uint64_t *values, + uint32_t count) +{ + struct rte_metrics_meta_s *entry; + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + uint16_t idx_metric; + uint16_t idx_value; + uint16_t cnt_setsize; + + if (port_id != RTE_METRICS_GLOBAL && + (port_id < 0 || port_id > RTE_MAX_ETHPORTS)) + return -EINVAL; + + rte_metrics_init(); + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); + if (memzone == NULL) + return -EIO; + stats = memzone->addr; + + rte_spinlock_lock(&stats->lock); + idx_metric = key; + cnt_setsize = 1; + while (idx_metric < stats->cnt_stats) { + entry = &stats->metadata[idx_metric]; + if (entry->idx_next_stat == 0) + break; + cnt_setsize++; + idx_metric++; + } + /* Check update does not cross set border */ + if (count > cnt_setsize) { + rte_spinlock_unlock(&stats->lock); + return -ERANGE; + } + + if (port_id == RTE_METRICS_GLOBAL) + for (idx_value = 0; idx_value < count; idx_value++) { + idx_metric = key + idx_value; + stats->metadata[idx_metric].nonport_value = + values[idx_value]; + } + else + for (idx_value = 0; idx_value < count; idx_value++) { + idx_metric = key + idx_value; + stats->metadata[idx_metric].value[port_id] = + values[idx_value]; + } + rte_spinlock_unlock(&stats->lock); + return 0; +} + +int +rte_metrics_get_names(struct rte_metric_name *names, + uint16_t capacity) +{ + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + uint16_t idx_name; + int return_value; + + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); + /* If not allocated, fail silently */ + if (memzone == NULL) + return 0; + + stats = memzone->addr; + rte_spinlock_lock(&stats->lock); + if (names != NULL) { + if (capacity < stats->cnt_stats) { + return_value = stats->cnt_stats; + rte_spinlock_unlock(&stats->lock); + return return_value; + } + for (idx_name = 0; idx_name < stats->cnt_stats; idx_name++) + strncpy(names[idx_name].name, + stats->metadata[idx_name].name, + RTE_METRICS_MAX_NAME_LEN); + } + return_value = stats->cnt_stats; + rte_spinlock_unlock(&stats->lock); + return return_value; +} + +int +rte_metrics_get_values(int port_id, + struct rte_metric_value *values, + uint16_t capacity) +{ + struct rte_metrics_meta_s *entry; + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + uint16_t idx_name; + int return_value; + + if (port_id != RTE_METRICS_GLOBAL && + (port_id < 0 || port_id > RTE_MAX_ETHPORTS)) + return -EINVAL; + + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); + /* If not allocated, fail silently */ + if (memzone == NULL) + return 0; + stats = memzone->addr; + rte_spinlock_lock(&stats->lock); + + if (values != NULL) { + if (capacity < stats->cnt_stats) { + return_value = stats->cnt_stats; + rte_spinlock_unlock(&stats->lock); + return return_value; + } + if (port_id == RTE_METRICS_GLOBAL) + for (idx_name = 0; + idx_name < stats->cnt_stats; + idx_name++) { + entry = &stats->metadata[idx_name]; + values[idx_name].key = idx_name; + values[idx_name].value = entry->nonport_value; + } + else + for (idx_name = 0; + idx_name < stats->cnt_stats; + idx_name++) { + entry = &stats->metadata[idx_name]; + values[idx_name].key = idx_name; + values[idx_name].value = entry->value[port_id]; + } + } + return_value = stats->cnt_stats; + rte_spinlock_unlock(&stats->lock); + return return_value; +} diff --git a/lib/librte_metrics/rte_metrics.h b/lib/librte_metrics/rte_metrics.h new file mode 100644 index 0000000..fd82af9 --- /dev/null +++ b/lib/librte_metrics/rte_metrics.h @@ -0,0 +1,223 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * + * RTE Metrics module + * + * Metric information is populated using a push model, where the + * information provider calls an update function on the relevant + * metrics. Currently only bulk querying of metrics is supported. + */ + +#ifndef _RTE_METRICS_H_ +#define _RTE_METRICS_H_ + +/** Maximum length of metric name (including null-terminator) */ +#define RTE_METRICS_MAX_NAME_LEN 64 + +/** + * Global (rather than port-specific) metric. + * + * When used instead of port number by rte_metrics_update_metric() + * or rte_metrics_update_metric(), the global metrics, which are + * not associated with any specific port, are updated. + */ +#define RTE_METRICS_GLOBAL -1 + + +/** + * A name-key lookup for metrics. + * + * An array of this structure is returned by rte_metrics_get_names(). + * The struct rte_eth_stats references these names via their array index. + */ +struct rte_metric_name { + /** String describing metric */ + char name[RTE_METRICS_MAX_NAME_LEN]; +}; + + +/** + * Metric value structure. + * + * This structure is used by rte_metrics_get_values() to return metrics, + * which are statistics that are not generated by PMDs. It maps a name key, + * which corresponds to an index in the array returned by + * rte_metrics_get_names(). + */ +struct rte_metric_value { + /** Numeric identifier of metric. */ + uint16_t key; + /** Value for metric */ + uint64_t value; +}; + + +/** + * Initializes metric module. This only has to be explicitly called if you + * intend to use rte_metrics_reg_metric() or rte_metrics_reg_metrics() from a + * secondary process. This function must be called from a primary process. + */ +void rte_metrics_init(void); + +/** + * Register a metric, making it available as a reporting parameter. + * + * Registering a metric is the way third-parties declare a parameter + * that they wish to be reported. Once registered, the associated + * numeric key can be obtained via rte_metrics_get_names(), which + * is required for updating said metric's value. + * + * @param name + * Metric name + * + * @return + * - Zero or positive: Success + * - Negative: Failure + */ +int rte_metrics_reg_metric(const char *name); + +/** + * Register a set of metrics. + * + * This is a bulk version of rte_metrics_reg_metrics() and aside from + * handling multiple keys at once is functionally identical. + * + * @param names + * List of metric names + * + * @param cnt_names + * Number of metrics in set + * + * @return + * - Zero or positive: Success + * - Negative: Failure + */ +int rte_metrics_reg_metrics(const char * const *names, uint16_t cnt_names); + +/** + * Get metric name-key lookup table. + * + * @param names + * A struct rte_metric_name array of at least *capacity* in size to + * receive key names. If this is NULL, function returns the required + * number of elements for this array. + * + * @param capacity + * Size (number of elements) of struct rte_metric_name array. + * Disregarded if names is NULL. + * + * @return + * - Positive value above capacity: error, *names* is too small. + * Return value is required size. + * - Positive value equal or less than capacity: Success. Return + * value is number of elements filled in. + * - Negative value: error. + */ +int rte_metrics_get_names( + struct rte_metric_name *names, + uint16_t capacity); + +/** + * Get metric value table. + * + * @param port_id + * Port id to query + * + * @param values + * A struct rte_metric_value array of at least *capacity* in size to + * receive metric ids and values. If this is NULL, function returns + * the required number of elements for this array. + * + * @param capacity + * Size (number of elements) of struct rte_metric_value array. + * Disregarded if names is NULL. + * + * @return + * - Positive value above capacity: error, *values* is too small. + * Return value is required size. + * - Positive value equal or less than capacity: Success. Return + * value is number of elements filled in. + * - Negative value: error. + */ +int rte_metrics_get_values( + int port_id, + struct rte_metric_value *values, + uint16_t capacity); + +/** + * Updates a metric + * + * @param port_id + * Port to update metrics for + * @param key + * Id of metric to update + * @param value + * New value + * + * @return + * - -EIO if unable to access shared metrics memory + * - Zero on success + */ +int rte_metrics_update_metric( + int port_id, + uint16_t key, + const uint64_t value); + +/** + * Updates a metric set. Note that it is an error to try to + * update across a set boundary. + * + * @param port_id + * Port to update metrics for + * @param key + * Base id of metrics set to update + * @param values + * Set of new values + * @param count + * Number of new values + * + * @return + * - -ERANGE if count exceeds metric set size + * - -EIO if upable to access shared metrics memory + * - Zero on success + */ +int rte_metrics_update_metrics( + int port_id, + uint16_t key, + const uint64_t *values, + uint32_t count); + +#endif diff --git a/lib/librte_metrics/rte_metrics_version.map b/lib/librte_metrics/rte_metrics_version.map new file mode 100644 index 0000000..f904814 --- /dev/null +++ b/lib/librte_metrics/rte_metrics_version.map @@ -0,0 +1,13 @@ +DPDK_17.02 { + global: + + rte_metrics_get_names; + rte_metrics_get_values; + rte_metrics_init; + rte_metrics_reg_metric; + rte_metrics_reg_metrics; + rte_metrics_update_metric; + rte_metrics_update_metrics; + + local: *; +}; diff --git a/mk/rte.app.mk b/mk/rte.app.mk index f75f0e2..40fcf33 100644 --- a/mk/rte.app.mk +++ b/mk/rte.app.mk @@ -98,6 +98,8 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_RING) += -lrte_ring _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL) += -lrte_eal _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE) += -lrte_cmdline _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE) += -lrte_cfgfile +_LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS) += -lrte_metrics + _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += -lrte_pmd_bond _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += -lrte_pmd_xenvirt -lxenstore -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [PATCH v7 1/6] lib: add information metrics library 2017-01-16 16:19 ` [dpdk-dev] [PATCH v7 1/6] lib: add information metrics library Remy Horton @ 2017-01-17 11:01 ` Van Haaren, Harry 2017-01-17 13:40 ` Remy Horton 0 siblings, 1 reply; 115+ messages in thread From: Van Haaren, Harry @ 2017-01-17 11:01 UTC (permalink / raw) To: Horton, Remy, dev; +Cc: Thomas Monjalon > -----Original Message----- > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Remy Horton > This patch adds a new information metric library that allows other > modules to register named metrics and update their values. It is > intended to be independent of ethdev, rather than mixing ethdev > and non-ethdev information in xstats. > > Signed-off-by: Remy Horton <remy.horton@intel.com> Comments inline below. > diff --git a/MAINTAINERS b/MAINTAINERS > index 9645c9b..4a19497 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -596,6 +596,11 @@ F: lib/librte_jobstats/ > F: examples/l2fwd-jobstats/ > F: doc/guides/sample_app_ug/l2_forward_job_stats.rst > > +Metrics > +M: Remy Horton <remy.horton@intel.com> > +F: lib/librte_metrics/ > +F: doc/guides/sample_app_ug/keep_alive.rst Copy paste error, Keep alive sample app guide should not be here. There is no sample app / guide for usage of the metrics library in this patchset as it is. > +++ b/lib/librte_metrics/rte_metrics.c > @@ -0,0 +1,310 @@ > +/*- > + * BSD LICENSE > + * > + * Copyright(c) 2016 Intel Corporation. All rights reserved. > + * All rights reserved. Update to 2016-2017 > +/** > + * Internal stats metadata and value entry. > + * > + * @internal > + * @param name > + * Name of metric > + * @param value > + * Current value for metric > + * @param idx_next_set > + * Index of next root element (zero for none) > + * @param idx_next_metric > + * Index of next metric in set (zero for none) > + * > + * Only the root of each set needs idx_next_set but since it has to be > + * assumed that number of sets could equal total number of metrics, > + * having a separate set metadata table doesn't save any memory. > + */ > +struct rte_metrics_meta_s { > + char name[RTE_METRICS_MAX_NAME_LEN]; > + uint64_t value[RTE_MAX_ETHPORTS]; > + uint64_t nonport_value; > + uint16_t idx_next_set; > + uint16_t idx_next_stat; > +}; Nit: why the _s in rte_metrics_meta_s? Is there a reason why struct rte_metrics_meta { is not suitable? Same question for rte_metrics_data_s. > +void > +rte_metrics_init(void) > +{ > + struct rte_metrics_data_s *stats; > + const struct rte_memzone *memzone; > + > + if (rte_eal_process_type() != RTE_PROC_PRIMARY) > + return; > + > + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); > + if (memzone != NULL) > + return; > + memzone = rte_memzone_reserve(RTE_METRICS_MEMZONE_NAME, > + sizeof(struct rte_metrics_data_s), rte_socket_id(), 0); In my opinion, passing socket_id to rte_metrics_init() would be a better API, than relying on the metrics initialization core to be on the correct socket. > + if (memzone == NULL) > + rte_exit(EXIT_FAILURE, "Unable to allocate stats memzone\n"); > + stats = memzone->addr; > + memset(stats, 0, sizeof(struct rte_metrics_data_s)); > + rte_spinlock_init(&stats->lock); Should this spinlock be initialized before the creation of the memzone? Creating the memzone first, and later initializing the locking-structure for it feels racey to me. The lock should probably be taken and unlocked again after init and memset. > +} > + > +int > +rte_metrics_reg_metric(const char *name) > +{ Nit: would rte_metrics_reg_name() be a better function name? > + const char * const list_names[] = {name}; > + > + return rte_metrics_reg_metrics(list_names, 1); > +} > + > +int > +rte_metrics_reg_metrics(const char * const *names, uint16_t cnt_names) > +{ Nit: would rte_metrics_reg_names() be a better function name? > + > +int > +rte_metrics_update_metric(int port_id, uint16_t key, const uint64_t value) > +{ Would rte_metrics_update_single() be a better function name? I presume updating a single metric at a time is exception case, and the (see below) more generic rte_metrics_update() would be more commonly used. > + return rte_metrics_update_metrics(port_id, key, &value, 1); > +} > + > +int > +rte_metrics_update_metrics(int port_id, > + uint16_t key, > + const uint64_t *values, > + uint32_t count) Would rte_metrics_update() be a better function name? > +{ > + struct rte_metrics_meta_s *entry; > + struct rte_metrics_data_s *stats; > + const struct rte_memzone *memzone; > + uint16_t idx_metric; > + uint16_t idx_value; > + uint16_t cnt_setsize; > + > + if (port_id != RTE_METRICS_GLOBAL && > + (port_id < 0 || port_id > RTE_MAX_ETHPORTS)) > + return -EINVAL; > + > + rte_metrics_init(); See above comments on rte_metrics_init() taking a socket_id parameter. Here any core could call update_metrics(), and if the library was not yet initialized, the memory for metrics would end up on the socket of this core. This should be avoided by A) adding socket_id parameter to the metrics_init() function B) Demanding that metrics_init() is called by the application before any core uses update_metrics() > + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); > + if (memzone == NULL) > + return -EIO; > + stats = memzone->addr; > + > + rte_spinlock_lock(&stats->lock); > + idx_metric = key; > + cnt_setsize = 1; > + while (idx_metric < stats->cnt_stats) { > + entry = &stats->metadata[idx_metric]; > + if (entry->idx_next_stat == 0) > + break; > + cnt_setsize++; > + idx_metric++; > + } > + /* Check update does not cross set border */ > + if (count > cnt_setsize) { > + rte_spinlock_unlock(&stats->lock); > + return -ERANGE; > + } What is a "set border"? I think this ensures that one set of metrics cannot overwrite the index's of another metrics set - correct? > + > + if (port_id == RTE_METRICS_GLOBAL) > + for (idx_value = 0; idx_value < count; idx_value++) { > + idx_metric = key + idx_value; > + stats->metadata[idx_metric].nonport_value = > + values[idx_value]; > + } > + else > + for (idx_value = 0; idx_value < count; idx_value++) { > + idx_metric = key + idx_value; > + stats->metadata[idx_metric].value[port_id] = > + values[idx_value]; > + } > + rte_spinlock_unlock(&stats->lock); > + return 0; > +} <snip> > diff --git a/lib/librte_metrics/rte_metrics.h b/lib/librte_metrics/rte_metrics.h > new file mode 100644 > index 0000000..fd82af9 > --- /dev/null > +++ b/lib/librte_metrics/rte_metrics.h > @@ -0,0 +1,223 @@ > +/*- > + * BSD LICENSE > + * > + * Copyright(c) 2016 Intel Corporation. All rights reserved. > + * All rights reserved. Add -2017 > + > + > +/** > + * Initializes metric module. This only has to be explicitly called if you > + * intend to use rte_metrics_reg_metric() or rte_metrics_reg_metrics() from a > + * secondary process. This function must be called from a primary process. > + */ > +void rte_metrics_init(void); As noted in the C function above: - accept a socket-id - demand an application calls it if it will use the metrics library. <snip> ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [PATCH v7 1/6] lib: add information metrics library 2017-01-17 11:01 ` Van Haaren, Harry @ 2017-01-17 13:40 ` Remy Horton 2017-01-17 14:23 ` Van Haaren, Harry 0 siblings, 1 reply; 115+ messages in thread From: Remy Horton @ 2017-01-17 13:40 UTC (permalink / raw) To: Van Haaren, Harry, dev; +Cc: Thomas Monjalon On 17/01/2017 11:01, Van Haaren, Harry wrote: >> -----Original Message----- >> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Remy Horton [..] > Nit: why the _s in rte_metrics_meta_s? Is there a reason why struct > rte_metrics_meta { is not suitable? Same question for > rte_metrics_data_s. Think it was originally to avoid a namespace collision, and I left the suffix in because this is an internal data-structure. >> + if (memzone == NULL) >> + rte_exit(EXIT_FAILURE, "Unable to allocate stats memzone\n"); >> + stats = memzone->addr; >> + memset(stats, 0, sizeof(struct rte_metrics_data_s)); >> + rte_spinlock_init(&stats->lock); > > Should this spinlock be initialized before the creation of the > memzone? Creating the memzone first, and later initializing the > locking-structure for it feels racey to me. The lock should probably > be taken and unlocked again after init and memset. Problem is the lock being part of the reserved memzone allocation. It is in there so that secondary processes can use the lock. > Nit: would rte_metrics_reg_name() be a better function name? [..] > Nit: would rte_metrics_reg_names() be a better function name? Agree. Done. > Would rte_metrics_update_single() be a better function name? [..] > Would rte_metrics_update() be a better function name? Think rte_metrics_update_value & rte_metrics_update_values would make a better pair. My preference at the moment is not to nominate a preferred one. >> + if (port_id != RTE_METRICS_GLOBAL && >> + (port_id < 0 || port_id > RTE_MAX_ETHPORTS)) >> + return -EINVAL; >> + >> + rte_metrics_init(); > > See above comments on rte_metrics_init() taking a socket_id parameter. Here any core could call update_metrics(), and if the library was not yet initialized, the memory for metrics would end up on the socket of this core. This should be avoided by > A) adding socket_id parameter to the metrics_init() function > B) Demanding that metrics_init() is called by the application before any core uses update_metrics() Done. Should also help alleviate the race. > What is a "set border"? I think this ensures that one set of metrics > cannot overwrite the index's of another metrics set - correct? It is intended to stop things like: idx1 = rte_metrics_reg_names(some_names, 2); idx2 = rte_metrics_reg_names(more_names, 3); ... rte_metrics_update_values(port_id, idx1, &new_values, 5); as the above assumes idx2=idx1+2 which is not guaranteed in concurrent enviornments ..Remy ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [PATCH v7 1/6] lib: add information metrics library 2017-01-17 13:40 ` Remy Horton @ 2017-01-17 14:23 ` Van Haaren, Harry 0 siblings, 0 replies; 115+ messages in thread From: Van Haaren, Harry @ 2017-01-17 14:23 UTC (permalink / raw) To: Horton, Remy, dev; +Cc: Thomas Monjalon > -----Original Message----- > From: Horton, Remy > Sent: Tuesday, January 17, 2017 1:40 PM > To: Van Haaren, Harry <harry.van.haaren@intel.com>; dev@dpdk.org > Cc: Thomas Monjalon <thomas.monjalon@6wind.com> > Subject: Re: [dpdk-dev] [PATCH v7 1/6] lib: add information metrics library > > > On 17/01/2017 11:01, Van Haaren, Harry wrote: > >> -----Original Message----- > >> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Remy Horton > [..] > > Nit: why the _s in rte_metrics_meta_s? Is there a reason why struct > > rte_metrics_meta { is not suitable? Same question for > > rte_metrics_data_s. > > Think it was originally to avoid a namespace collision, and I left the > suffix in because this is an internal data-structure. OK. > >> + if (memzone == NULL) > >> + rte_exit(EXIT_FAILURE, "Unable to allocate stats memzone\n"); > >> + stats = memzone->addr; > >> + memset(stats, 0, sizeof(struct rte_metrics_data_s)); > >> + rte_spinlock_init(&stats->lock); > > > > Should this spinlock be initialized before the creation of the > > memzone? Creating the memzone first, and later initializing the > > locking-structure for it feels racey to me. The lock should probably > > be taken and unlocked again after init and memset. > > Problem is the lock being part of the reserved memzone allocation. It is > in there so that secondary processes can use the lock. Ah ok - apologies I missed that the lock is in the memory itself. > > > Nit: would rte_metrics_reg_name() be a better function name? > [..] > > Nit: would rte_metrics_reg_names() be a better function name? > > Agree. Done. Great > > Would rte_metrics_update_single() be a better function name? > [..] > > Would rte_metrics_update() be a better function name? > > Think rte_metrics_update_value & rte_metrics_update_values would make a > better pair. My preference at the moment is not to nominate a preferred one. > > > >> + if (port_id != RTE_METRICS_GLOBAL && > >> + (port_id < 0 || port_id > RTE_MAX_ETHPORTS)) > >> + return -EINVAL; > >> + > >> + rte_metrics_init(); > > > > See above comments on rte_metrics_init() taking a socket_id parameter. Here any core > could call update_metrics(), and if the library was not yet initialized, the memory for > metrics would end up on the socket of this core. This should be avoided by > > A) adding socket_id parameter to the metrics_init() function > > B) Demanding that metrics_init() is called by the application before any core uses > update_metrics() > > Done. Should also help alleviate the race. Cool. > > What is a "set border"? I think this ensures that one set of metrics > > cannot overwrite the index's of another metrics set - correct? > > It is intended to stop things like: > > idx1 = rte_metrics_reg_names(some_names, 2); > idx2 = rte_metrics_reg_names(more_names, 3); > ... > rte_metrics_update_values(port_id, idx1, &new_values, 5); > > as the above assumes idx2=idx1+2 which is not guaranteed in concurrent > enviornments That confirms my understanding - thanks. ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v7 2/6] app/proc_info: add metrics displaying 2017-01-16 16:19 ` [dpdk-dev] [PATCH v7 0/6] " Remy Horton 2017-01-16 16:19 ` [dpdk-dev] [PATCH v7 1/6] lib: add information metrics library Remy Horton @ 2017-01-16 16:19 ` Remy Horton 2017-01-17 11:08 ` Van Haaren, Harry 2017-01-16 16:19 ` [dpdk-dev] [PATCH v7 3/6] lib: add bitrate statistics library Remy Horton ` (4 subsequent siblings) 6 siblings, 1 reply; 115+ messages in thread From: Remy Horton @ 2017-01-16 16:19 UTC (permalink / raw) To: dev; +Cc: Reshma Pattan, Thomas Monjalon From: Reshma Pattan <reshma.pattan@intel.com> Modify the dpdk-procinfo process to display the newly added metrics. Added new command line option "--metrics" to display metrics. Signed-off-by: Reshma Pattan <reshma.pattan@intel.com> Signed-off-by: Remy Horton <remy.horton@intel.com> --- app/proc_info/main.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/app/proc_info/main.c b/app/proc_info/main.c index 2c56d10..e5d626e 100644 --- a/app/proc_info/main.c +++ b/app/proc_info/main.c @@ -57,6 +57,7 @@ #include <rte_atomic.h> #include <rte_branch_prediction.h> #include <rte_string_fns.h> +#include <rte_metrics.h> /* Maximum long option length for option parsing. */ #define MAX_LONG_OPT_SZ 64 @@ -68,6 +69,8 @@ static uint32_t enabled_port_mask; static uint32_t enable_stats; /**< Enable xstats. */ static uint32_t enable_xstats; +/**< Enable metrics. */ +static uint32_t enable_metrics; /**< Enable stats reset. */ static uint32_t reset_stats; /**< Enable xstats reset. */ @@ -85,6 +88,8 @@ proc_info_usage(const char *prgname) " --stats: to display port statistics, enabled by default\n" " --xstats: to display extended port statistics, disabled by " "default\n" + " --metrics: to display derived metrics of the ports, disabled by " + "default\n" " --stats-reset: to reset port statistics\n" " --xstats-reset: to reset port extended statistics\n", prgname); @@ -127,6 +132,7 @@ proc_info_parse_args(int argc, char **argv) {"stats", 0, NULL, 0}, {"stats-reset", 0, NULL, 0}, {"xstats", 0, NULL, 0}, + {"metrics", 0, NULL, 0}, {"xstats-reset", 0, NULL, 0}, {NULL, 0, 0, 0} }; @@ -159,6 +165,10 @@ proc_info_parse_args(int argc, char **argv) else if (!strncmp(long_option[option_index].name, "xstats", MAX_LONG_OPT_SZ)) enable_xstats = 1; + else if (!strncmp(long_option[option_index].name, + "metrics", + MAX_LONG_OPT_SZ)) + enable_metrics = 1; /* Reset stats */ if (!strncmp(long_option[option_index].name, "stats-reset", MAX_LONG_OPT_SZ)) @@ -301,6 +311,63 @@ nic_xstats_clear(uint8_t port_id) printf("\n NIC extended statistics for port %d cleared\n", port_id); } +static void +metrics_display(int port_id) +{ + struct rte_metric_value *metrics; + struct rte_metric_name *names; + int len, ret; + static const char *nic_stats_border = "########################"; + + memset(&metrics, 0, sizeof(struct rte_metric_value)); + len = rte_metrics_get_names(NULL, 0); + if (len < 0) { + printf("Cannot get metrics count\n"); + return; + } + + metrics = malloc(sizeof(struct rte_metric_value) * len); + if (metrics == NULL) { + printf("Cannot allocate memory for metrics\n"); + return; + } + + names = malloc(sizeof(struct rte_metric_name) * len); + if (names == NULL) { + printf("Cannot allocate memory for metrcis names\n"); + free(metrics); + return; + } + + if (len != rte_metrics_get_names(names, len)) { + printf("Cannot get metrics names\n"); + free(metrics); + free(names); + return; + } + + if (port_id == RTE_METRICS_GLOBAL) + printf("###### Non port specific metrics #########\n"); + else + printf("###### metrics for port %-2d #########\n", port_id); + printf("%s############################\n", nic_stats_border); + ret = rte_metrics_get_values(port_id, metrics, len); + if (ret < 0 || ret > len) { + printf("Cannot get metrics values\n"); + free(metrics); + free(names); + return; + } + + int i; + for (i = 0; i < len; i++) + printf("%s: %"PRIu64"\n", names[i].name, metrics[i].value); + + printf("%s############################\n", nic_stats_border); + free(metrics); + free(names); +} + int main(int argc, char **argv) { @@ -360,8 +427,14 @@ main(int argc, char **argv) nic_stats_clear(i); else if (reset_xstats) nic_xstats_clear(i); + else if (enable_metrics) + metrics_display(i); } } + /* print port independent stats */ + if (enable_metrics) + metrics_display(RTE_METRICS_GLOBAL); + return 0; } -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [PATCH v7 2/6] app/proc_info: add metrics displaying 2017-01-16 16:19 ` [dpdk-dev] [PATCH v7 2/6] app/proc_info: add metrics displaying Remy Horton @ 2017-01-17 11:08 ` Van Haaren, Harry 2017-01-17 14:27 ` Remy Horton 0 siblings, 1 reply; 115+ messages in thread From: Van Haaren, Harry @ 2017-01-17 11:08 UTC (permalink / raw) To: Horton, Remy, dev; +Cc: Pattan, Reshma, Thomas Monjalon > -----Original Message----- > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Remy Horton > Sent: Monday, January 16, 2017 4:19 PM > To: dev@dpdk.org > Cc: Pattan, Reshma <reshma.pattan@intel.com>; Thomas Monjalon <thomas.monjalon@6wind.com> > Subject: [dpdk-dev] [PATCH v7 2/6] app/proc_info: add metrics displaying > > From: Reshma Pattan <reshma.pattan@intel.com> > > Modify the dpdk-procinfo process to display the newly added metrics. > Added new command line option "--metrics" to display metrics. > > Signed-off-by: Reshma Pattan <reshma.pattan@intel.com> > Signed-off-by: Remy Horton <remy.horton@intel.com> Note that current git HEAD has a bug in secondary process - this has already been raised and fixed in patches on the ML. In testing, I manually fixed the secondary proc issue, after which testing here worked successfully. Comments inline. > --- > app/proc_info/main.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 73 insertions(+) > > diff --git a/app/proc_info/main.c b/app/proc_info/main.c > index 2c56d10..e5d626e 100644 > --- a/app/proc_info/main.c > +++ b/app/proc_info/main.c > @@ -57,6 +57,7 @@ > #include <rte_atomic.h> > #include <rte_branch_prediction.h> > #include <rte_string_fns.h> > +#include <rte_metrics.h> > > /* Maximum long option length for option parsing. */ > #define MAX_LONG_OPT_SZ 64 > @@ -68,6 +69,8 @@ static uint32_t enabled_port_mask; > static uint32_t enable_stats; > /**< Enable xstats. */ > static uint32_t enable_xstats; > +/**< Enable metrics. */ > +static uint32_t enable_metrics; > /**< Enable stats reset. */ > static uint32_t reset_stats; > /**< Enable xstats reset. */ > @@ -85,6 +88,8 @@ proc_info_usage(const char *prgname) > " --stats: to display port statistics, enabled by default\n" > " --xstats: to display extended port statistics, disabled by " > "default\n" > + " --metrics: to display derived metrics of the ports, disabled by " > + "default\n" > " --stats-reset: to reset port statistics\n" > " --xstats-reset: to reset port extended statistics\n", I presume there is no need for a --metrics-reset as the values are reset when printed, correct? > prgname); > @@ -127,6 +132,7 @@ proc_info_parse_args(int argc, char **argv) > {"stats", 0, NULL, 0}, > {"stats-reset", 0, NULL, 0}, > {"xstats", 0, NULL, 0}, > + {"metrics", 0, NULL, 0}, > {"xstats-reset", 0, NULL, 0}, > {NULL, 0, 0, 0} > }; > @@ -159,6 +165,10 @@ proc_info_parse_args(int argc, char **argv) > else if (!strncmp(long_option[option_index].name, "xstats", > MAX_LONG_OPT_SZ)) > enable_xstats = 1; > + else if (!strncmp(long_option[option_index].name, > + "metrics", > + MAX_LONG_OPT_SZ)) > + enable_metrics = 1; > /* Reset stats */ > if (!strncmp(long_option[option_index].name, "stats-reset", > MAX_LONG_OPT_SZ)) > @@ -301,6 +311,63 @@ nic_xstats_clear(uint8_t port_id) > printf("\n NIC extended statistics for port %d cleared\n", port_id); > } > > +static void > +metrics_display(int port_id) > +{ > + struct rte_metric_value *metrics; > + struct rte_metric_name *names; > + int len, ret; > + static const char *nic_stats_border = "########################"; > + > + memset(&metrics, 0, sizeof(struct rte_metric_value)); > + len = rte_metrics_get_names(NULL, 0); > + if (len < 0) { > + printf("Cannot get metrics count\n"); > + return; > + } > + > + metrics = malloc(sizeof(struct rte_metric_value) * len); > + if (metrics == NULL) { > + printf("Cannot allocate memory for metrics\n"); > + return; > + } Is malloc() favoured over rte_malloc() for a reason? > + > + names = malloc(sizeof(struct rte_metric_name) * len); > + if (names == NULL) { > + printf("Cannot allocate memory for metrcis names\n"); > + free(metrics); > + return; > + } > + > + if (len != rte_metrics_get_names(names, len)) { > + printf("Cannot get metrics names\n"); > + free(metrics); > + free(names); > + return; > + } > + > + if (port_id == RTE_METRICS_GLOBAL) > + printf("###### Non port specific metrics #########\n"); > + else > + printf("###### metrics for port %-2d #########\n", port_id); > + printf("%s############################\n", nic_stats_border); > + ret = rte_metrics_get_values(port_id, metrics, len); > + if (ret < 0 || ret > len) { > + printf("Cannot get metrics values\n"); > + free(metrics); > + free(names); > + return; > + } > + > + int i; > + for (i = 0; i < len; i++) > + printf("%s: %"PRIu64"\n", names[i].name, metrics[i].value); > + > + printf("%s############################\n", nic_stats_border); > + free(metrics); > + free(names); > +} > + > int > main(int argc, char **argv) > { > @@ -360,8 +427,14 @@ main(int argc, char **argv) > nic_stats_clear(i); > else if (reset_xstats) > nic_xstats_clear(i); > + else if (enable_metrics) > + metrics_display(i); > } > } > > + /* print port independent stats */ > + if (enable_metrics) > + metrics_display(RTE_METRICS_GLOBAL); > + > return 0; > } > -- > 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [PATCH v7 2/6] app/proc_info: add metrics displaying 2017-01-17 11:08 ` Van Haaren, Harry @ 2017-01-17 14:27 ` Remy Horton 0 siblings, 0 replies; 115+ messages in thread From: Remy Horton @ 2017-01-17 14:27 UTC (permalink / raw) To: Van Haaren, Harry, dev; +Cc: Pattan, Reshma, Thomas Monjalon On 17/01/2017 11:08, Van Haaren, Harry wrote: [..] >> + " --metrics: to display derived metrics of the ports, disabled by " >> + "default\n" [..] > I presume there is no need for a --metrics-reset as the values are reset when printed, correct? Reset is not (currently) supported, as some of the expected future use of metrics is informational values that are not continually updated. > Is malloc() favoured over rte_malloc() for a reason? None I am aware of. There is a recent-ish preference for rte_malloc() over malloc() in new code, so will update.. ..Remy ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v7 3/6] lib: add bitrate statistics library 2017-01-16 16:19 ` [dpdk-dev] [PATCH v7 0/6] " Remy Horton 2017-01-16 16:19 ` [dpdk-dev] [PATCH v7 1/6] lib: add information metrics library Remy Horton 2017-01-16 16:19 ` [dpdk-dev] [PATCH v7 2/6] app/proc_info: add metrics displaying Remy Horton @ 2017-01-16 16:19 ` Remy Horton 2017-01-17 11:16 ` Van Haaren, Harry 2017-01-16 16:19 ` [dpdk-dev] [PATCH v7 4/6] app/test-pmd: add bitrate statistics calculation Remy Horton ` (3 subsequent siblings) 6 siblings, 1 reply; 115+ messages in thread From: Remy Horton @ 2017-01-16 16:19 UTC (permalink / raw) To: dev; +Cc: Thomas Monjalon This patch adds a library that calculates peak and average data-rate statistics. For ethernet devices. These statistics are reported using the metrics library. Signed-off-by: Remy Horton <remy.horton@intel.com> --- MAINTAINERS | 4 + config/common_base | 5 + doc/api/doxy-api-index.md | 1 + doc/api/doxy-api.conf | 1 + doc/guides/rel_notes/release_17_02.rst | 5 + lib/Makefile | 1 + lib/librte_bitratestats/Makefile | 53 +++++++++ lib/librte_bitratestats/rte_bitrate.c | 132 +++++++++++++++++++++ lib/librte_bitratestats/rte_bitrate.h | 80 +++++++++++++ .../rte_bitratestats_version.map | 9 ++ mk/rte.app.mk | 1 + 11 files changed, 292 insertions(+) create mode 100644 lib/librte_bitratestats/Makefile create mode 100644 lib/librte_bitratestats/rte_bitrate.c create mode 100644 lib/librte_bitratestats/rte_bitrate.h create mode 100644 lib/librte_bitratestats/rte_bitratestats_version.map diff --git a/MAINTAINERS b/MAINTAINERS index 4a19497..6cd9896 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -601,6 +601,10 @@ M: Remy Horton <remy.horton@intel.com> F: lib/librte_metrics/ F: doc/guides/sample_app_ug/keep_alive.rst +Bit-rate statistica +M: Remy Horton <remy.horton@intel.com> +F: lib/librte_bitratestats/ + Test Applications ----------------- diff --git a/config/common_base b/config/common_base index 0eb3866..decebe5 100644 --- a/config/common_base +++ b/config/common_base @@ -598,3 +598,8 @@ CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n # Compile the device metrics library # CONFIG_RTE_LIBRTE_METRICS=y + +# +# Compile the bitrate statistics library +# +CONFIG_RTE_LIBRTE_BITRATE=y diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md index 94f0f69..5e194b0 100644 --- a/doc/api/doxy-api-index.md +++ b/doc/api/doxy-api-index.md @@ -151,4 +151,5 @@ There are many libraries, so their headers may be grouped by topics: [ABI compat] (@ref rte_compat.h), [keepalive] (@ref rte_keepalive.h), [Device Metrics] (@ref rte_metrics.h), + [Bitrate Statistics] (@ref rte_bitrate.h), [version] (@ref rte_version.h) diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf index 194b670..6e6ab5c 100644 --- a/doc/api/doxy-api.conf +++ b/doc/api/doxy-api.conf @@ -35,6 +35,7 @@ INPUT = doc/api/doxy-api-index.md \ lib/librte_eal/common/include \ lib/librte_eal/common/include/generic \ lib/librte_acl \ + lib/librte_bitratestats \ lib/librte_cfgfile \ lib/librte_cmdline \ lib/librte_compat \ diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst index 4fca29b..44012c8 100644 --- a/doc/guides/rel_notes/release_17_02.rst +++ b/doc/guides/rel_notes/release_17_02.rst @@ -40,6 +40,11 @@ New Features intended to provide a reporting mechanism that is independent of the ethdev library. + * **Added bit-rate calculation library.** + + A library that can be used to calculate device bit-rates. Calculated + bitrates are reported using the metrics library. + This section is a comment. do not overwrite or remove it. Also, make sure to start the actual text at the margin. ========================================================= diff --git a/lib/Makefile b/lib/Makefile index 5d85dcf..e211bc0 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -59,6 +59,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += librte_pipeline DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics +DIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += librte_bitratestats ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni diff --git a/lib/librte_bitratestats/Makefile b/lib/librte_bitratestats/Makefile new file mode 100644 index 0000000..b725d4e --- /dev/null +++ b/lib/librte_bitratestats/Makefile @@ -0,0 +1,53 @@ +# BSD LICENSE +# +# Copyright(c) 2016 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +include $(RTE_SDK)/mk/rte.vars.mk + +# library name +LIB = librte_bitratestats.a + +CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) + +EXPORT_MAP := rte_bitratestats_version.map + +LIBABIVER := 1 + +# all source are stored in SRCS-y +SRCS-$(CONFIG_RTE_LIBRTE_BITRATE) := rte_bitrate.c + +# Install header file +SYMLINK-$(CONFIG_RTE_LIBRTE_BITRATE)-include += rte_bitrate.h + +DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_eal +DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_ether +DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_metrics + +include $(RTE_SDK)/mk/rte.lib.mk diff --git a/lib/librte_bitratestats/rte_bitrate.c b/lib/librte_bitratestats/rte_bitrate.c new file mode 100644 index 0000000..c8d9a20 --- /dev/null +++ b/lib/librte_bitratestats/rte_bitrate.c @@ -0,0 +1,132 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <rte_common.h> +#include <rte_ethdev.h> +#include <rte_malloc.h> +#include <rte_metrics.h> +#include <rte_bitrate.h> + +/* + * Persistent bit-rate data. + * @internal + */ +struct rte_stats_bitrate_s { + uint64_t last_ibytes; + uint64_t last_obytes; + uint64_t peak_ibits; + uint64_t peak_obits; + uint64_t ewma_ibits; + uint64_t ewma_obits; +}; + +struct rte_stats_bitrates_s { + struct rte_stats_bitrate_s port_stats[RTE_MAX_ETHPORTS]; + uint16_t id_stats_set; +}; + +struct rte_stats_bitrates_s * +rte_stats_bitrate_create(void) +{ + return rte_zmalloc(NULL, sizeof(struct rte_stats_bitrates_s), + RTE_CACHE_LINE_SIZE); +} + +int +rte_stats_bitrate_reg(struct rte_stats_bitrates_s *bitrate_data) +{ + const char * const names[] = { + "mean_bits_in", "mean_bits_out", + "peak_bits_in", "peak_bits_out", + }; + int return_value; + + return_value = rte_metrics_reg_metrics(&names[0], 4); + if (return_value >= 0) + bitrate_data->id_stats_set = return_value; + return return_value; +} + +int +rte_stats_bitrate_calc(struct rte_stats_bitrates_s *bitrate_data, + uint8_t port_id) +{ + struct rte_stats_bitrate_s *port_data; + struct rte_eth_stats eth_stats; + int ret_code; + uint64_t cnt_bits; + int64_t delta; + const int64_t alpha_percent = 20; + uint64_t values[4]; + + ret_code = rte_eth_stats_get(port_id, ð_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 [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [PATCH v7 3/6] lib: add bitrate statistics library 2017-01-16 16:19 ` [dpdk-dev] [PATCH v7 3/6] lib: add bitrate statistics library Remy Horton @ 2017-01-17 11:16 ` Van Haaren, Harry 2017-01-17 15:37 ` Remy Horton 0 siblings, 1 reply; 115+ messages in thread From: Van Haaren, Harry @ 2017-01-17 11:16 UTC (permalink / raw) To: Horton, Remy, dev; +Cc: Thomas Monjalon > -----Original Message----- > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Remy Horton > Sent: Monday, January 16, 2017 4:20 PM > To: dev@dpdk.org > Cc: Thomas Monjalon <thomas.monjalon@6wind.com> > Subject: [dpdk-dev] [PATCH v7 3/6] lib: add bitrate statistics library > > This patch adds a library that calculates peak and average data-rate > statistics. For ethernet devices. These statistics are reported using > the metrics library. > > Signed-off-by: Remy Horton <remy.horton@intel.com> Comments inline > --- > MAINTAINERS | 4 + > config/common_base | 5 + > doc/api/doxy-api-index.md | 1 + > doc/api/doxy-api.conf | 1 + > doc/guides/rel_notes/release_17_02.rst | 5 + > lib/Makefile | 1 + > lib/librte_bitratestats/Makefile | 53 +++++++++ > lib/librte_bitratestats/rte_bitrate.c | 132 +++++++++++++++++++++ > lib/librte_bitratestats/rte_bitrate.h | 80 +++++++++++++ > .../rte_bitratestats_version.map | 9 ++ > mk/rte.app.mk | 1 + > 11 files changed, 292 insertions(+) > create mode 100644 lib/librte_bitratestats/Makefile > create mode 100644 lib/librte_bitratestats/rte_bitrate.c > create mode 100644 lib/librte_bitratestats/rte_bitrate.h > create mode 100644 lib/librte_bitratestats/rte_bitratestats_version.map > > diff --git a/MAINTAINERS b/MAINTAINERS > index 4a19497..6cd9896 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -601,6 +601,10 @@ M: Remy Horton <remy.horton@intel.com> > F: lib/librte_metrics/ > F: doc/guides/sample_app_ug/keep_alive.rst > > +Bit-rate statistica > +M: Remy Horton <remy.horton@intel.com> > +F: lib/librte_bitratestats/ > + > > Test Applications > ----------------- > diff --git a/config/common_base b/config/common_base > index 0eb3866..decebe5 100644 > --- a/config/common_base > +++ b/config/common_base > @@ -598,3 +598,8 @@ CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n > # Compile the device metrics library > # > CONFIG_RTE_LIBRTE_METRICS=y > + > +# > +# Compile the bitrate statistics library > +# > +CONFIG_RTE_LIBRTE_BITRATE=y > diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md > index 94f0f69..5e194b0 100644 > --- a/doc/api/doxy-api-index.md > +++ b/doc/api/doxy-api-index.md > @@ -151,4 +151,5 @@ There are many libraries, so their headers may be grouped by topics: > [ABI compat] (@ref rte_compat.h), > [keepalive] (@ref rte_keepalive.h), > [Device Metrics] (@ref rte_metrics.h), > + [Bitrate Statistics] (@ref rte_bitrate.h), > [version] (@ref rte_version.h) > diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf > index 194b670..6e6ab5c 100644 > --- a/doc/api/doxy-api.conf > +++ b/doc/api/doxy-api.conf > @@ -35,6 +35,7 @@ INPUT = doc/api/doxy-api-index.md \ > lib/librte_eal/common/include \ > lib/librte_eal/common/include/generic \ > lib/librte_acl \ > + lib/librte_bitratestats \ > lib/librte_cfgfile \ > lib/librte_cmdline \ > lib/librte_compat \ > diff --git a/doc/guides/rel_notes/release_17_02.rst > b/doc/guides/rel_notes/release_17_02.rst > index 4fca29b..44012c8 100644 > --- a/doc/guides/rel_notes/release_17_02.rst > +++ b/doc/guides/rel_notes/release_17_02.rst > @@ -40,6 +40,11 @@ New Features > intended to provide a reporting mechanism that is independent of the > ethdev library. > > + * **Added bit-rate calculation library.** > + > + A library that can be used to calculate device bit-rates. Calculated > + bitrates are reported using the metrics library. > + > This section is a comment. do not overwrite or remove it. > Also, make sure to start the actual text at the margin. > ========================================================= > diff --git a/lib/Makefile b/lib/Makefile > index 5d85dcf..e211bc0 100644 > --- a/lib/Makefile > +++ b/lib/Makefile > @@ -59,6 +59,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += librte_pipeline > DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder > DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump > DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics > +DIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += librte_bitratestats > > ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) > DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni > diff --git a/lib/librte_bitratestats/Makefile b/lib/librte_bitratestats/Makefile > new file mode 100644 > index 0000000..b725d4e > --- /dev/null > +++ b/lib/librte_bitratestats/Makefile > @@ -0,0 +1,53 @@ > +# BSD LICENSE > +# > +# Copyright(c) 2016 Intel Corporation. All rights reserved. > +# All rights reserved. Add -2017 > +# > +# Redistribution and use in source and binary forms, with or without > +# modification, are permitted provided that the following conditions > +# are met: > +# > +# * Redistributions of source code must retain the above copyright > +# notice, this list of conditions and the following disclaimer. > +# * Redistributions in binary form must reproduce the above copyright > +# notice, this list of conditions and the following disclaimer in > +# the documentation and/or other materials provided with the > +# distribution. > +# * Neither the name of Intel Corporation nor the names of its > +# contributors may be used to endorse or promote products derived > +# from this software without specific prior written permission. > +# > +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS > +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT > +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR > +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT > +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, > +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT > +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, > +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY > +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT > +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE > +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > + > +include $(RTE_SDK)/mk/rte.vars.mk > + > +# library name > +LIB = librte_bitratestats.a > + > +CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) > + > +EXPORT_MAP := rte_bitratestats_version.map > + > +LIBABIVER := 1 > + > +# all source are stored in SRCS-y > +SRCS-$(CONFIG_RTE_LIBRTE_BITRATE) := rte_bitrate.c > + > +# Install header file > +SYMLINK-$(CONFIG_RTE_LIBRTE_BITRATE)-include += rte_bitrate.h > + > +DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_eal > +DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_ether > +DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_metrics > + > +include $(RTE_SDK)/mk/rte.lib.mk > diff --git a/lib/librte_bitratestats/rte_bitrate.c b/lib/librte_bitratestats/rte_bitrate.c > new file mode 100644 > index 0000000..c8d9a20 > --- /dev/null > +++ b/lib/librte_bitratestats/rte_bitrate.c > @@ -0,0 +1,132 @@ > +/*- > + * BSD LICENSE > + * > + * Copyright(c) 2016 Intel Corporation. All rights reserved. > + * All rights reserved. -2017 > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * > + * * Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * * Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in > + * the documentation and/or other materials provided with the > + * distribution. > + * * Neither the name of Intel Corporation nor the names of its > + * contributors may be used to endorse or promote products derived > + * from this software without specific prior written permission. > + * > + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS > + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT > + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR > + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT > + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, > + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT > + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, > + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY > + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT > + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE > + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > + */ > + > +#include <rte_common.h> > +#include <rte_ethdev.h> > +#include <rte_malloc.h> > +#include <rte_metrics.h> > +#include <rte_bitrate.h> > + > +/* > + * Persistent bit-rate data. > + * @internal > + */ > +struct rte_stats_bitrate_s { > + uint64_t last_ibytes; > + uint64_t last_obytes; > + uint64_t peak_ibits; > + uint64_t peak_obits; > + uint64_t ewma_ibits; > + uint64_t ewma_obits; > +}; Nit: same as previous metrics patch, any reason for the _s at the end? Same for following structs: > + > +struct rte_stats_bitrates_s { > + struct rte_stats_bitrate_s port_stats[RTE_MAX_ETHPORTS]; > + uint16_t id_stats_set; > +}; > + > +struct rte_stats_bitrates_s * > +rte_stats_bitrate_create(void) > +{ > + return rte_zmalloc(NULL, sizeof(struct rte_stats_bitrates_s), > + RTE_CACHE_LINE_SIZE); > +} Is the socket relevant here? Perhaps pass socket_id to the function, and use rte_zmalloc_socket(). This function has no way of initializing bitrate structs on two different sockets, using one a single setup thread. > + > +int > +rte_stats_bitrate_reg(struct rte_stats_bitrates_s *bitrate_data) > +{ > + const char * const names[] = { > + "mean_bits_in", "mean_bits_out", > + "peak_bits_in", "peak_bits_out", > + }; > + int return_value; > + > + return_value = rte_metrics_reg_metrics(&names[0], 4); > + if (return_value >= 0) > + bitrate_data->id_stats_set = return_value; > + return return_value; > +} > + > +int > +rte_stats_bitrate_calc(struct rte_stats_bitrates_s *bitrate_data, > + uint8_t port_id) > +{ > + struct rte_stats_bitrate_s *port_data; > + struct rte_eth_stats eth_stats; > + int ret_code; > + uint64_t cnt_bits; > + int64_t delta; > + const int64_t alpha_percent = 20; > + uint64_t values[4]; > + > + ret_code = rte_eth_stats_get(port_id, ð_stats); > + if (ret_code != 0) > + return ret_code; > + > + port_data = &bitrate_data->port_stats[port_id]; > + > + /* Incoming bitrate. This is an iteratively calculated EWMA > + * (Expomentially Weighted Moving Average) that uses a > + * weighting factor of alpha_percent. > + */ > + cnt_bits = (eth_stats.ibytes - port_data->last_ibytes) << 3; > + port_data->last_ibytes = eth_stats.ibytes; > + if (cnt_bits > port_data->peak_ibits) > + port_data->peak_ibits = cnt_bits; > + delta = cnt_bits; > + delta -= port_data->ewma_ibits; > + /* The +-50 fixes integer rounding during divison */ > + if (delta > 0) > + delta = (delta * alpha_percent + 50) / 100; > + else > + delta = (delta * alpha_percent - 50) / 100; > + port_data->ewma_ibits += delta; The integer +50 feels a bit odd, I'm not opposed to this if it works though. The latency stats uses a float alpha multiplier, is that a cleaner solution? The two libraries should probably be consistent anyway. > + > + /* Outgoing bitrate (also EWMA) */ > + cnt_bits = (eth_stats.obytes - port_data->last_obytes) << 3; > + port_data->last_obytes = eth_stats.obytes; > + if (cnt_bits > port_data->peak_obits) > + port_data->peak_obits = cnt_bits; > + delta = cnt_bits; > + delta -= port_data->ewma_obits; > + delta = (delta * alpha_percent + 50) / 100; Same float multiplier comment. > + port_data->ewma_obits += delta; > + > + values[0] = port_data->ewma_ibits; > + values[1] = port_data->ewma_obits; > + values[2] = port_data->peak_ibits; > + values[3] = port_data->peak_obits; > + rte_metrics_update_metrics(port_id, bitrate_data->id_stats_set, > + values, 4); > + return 0; > +} > diff --git a/lib/librte_bitratestats/rte_bitrate.h b/lib/librte_bitratestats/rte_bitrate.h > new file mode 100644 > index 0000000..bc87c5e > --- /dev/null > +++ b/lib/librte_bitratestats/rte_bitrate.h > @@ -0,0 +1,80 @@ > +/*- > + * BSD LICENSE > + * > + * Copyright(c) 2016 Intel Corporation. All rights reserved. > + * All rights reserved. -2017 > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * > + * * Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * * Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in > + * the documentation and/or other materials provided with the > + * distribution. > + * * Neither the name of Intel Corporation nor the names of its > + * contributors may be used to endorse or promote products derived > + * from this software without specific prior written permission. > + * > + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS > + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT > + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR > + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT > + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, > + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT > + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, > + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY > + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT > + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE > + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > + */ > + > + > +/** > + * Bitrate statistics data structure. > + * This data structure is intentionally opaque. > + */ > +struct rte_stats_bitrates_s; _s question as previously highlighted. > + > + > +/** > + * Allocate a bitrate statistics structure > + * > + * @return > + * - Pointer to structure on success > + * - NULL on error (zmalloc failure) > + */ > +struct rte_stats_bitrates_s *rte_stats_bitrate_create(void); > + > + > +/** > + * Register bitrate statistics with the metric library. > + * > + * @param bitrate_data > + * Pointer allocated by rte_stats_create() > + * > + * @return > + * Zero on success > + * Negative on error > + */ > +int rte_stats_bitrate_reg(struct rte_stats_bitrates_s *bitrate_data); > + > + > +/** > + * Calculate statistics for current time window. The period with which > + * this function is called should be the intended sampling window width. > + * > + * @param bitrate_data > + * Bitrate statistics data pointer > + * > + * @param port_id > + * Port id to calculate statistics for > + * > + * @return > + * - Zero on success > + * - Negative value on error > + */ > +int rte_stats_bitrate_calc(struct rte_stats_bitrates_s *bitrate_data, > + uint8_t port_id); > diff --git a/lib/librte_bitratestats/rte_bitratestats_version.map > b/lib/librte_bitratestats/rte_bitratestats_version.map > new file mode 100644 > index 0000000..66f232f > --- /dev/null > +++ b/lib/librte_bitratestats/rte_bitratestats_version.map > @@ -0,0 +1,9 @@ > +DPDK_17.02 { > + global: > + > + rte_stats_bitrate_calc; > + rte_stats_bitrate_create; > + rte_stats_bitrate_reg; > + > + local: *; > +}; > diff --git a/mk/rte.app.mk b/mk/rte.app.mk > index 40fcf33..6aac5ac 100644 > --- a/mk/rte.app.mk > +++ b/mk/rte.app.mk > @@ -99,6 +99,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL) += -lrte_eal > _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE) += -lrte_cmdline > _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE) += -lrte_cfgfile > _LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS) += -lrte_metrics > +_LDLIBS-$(CONFIG_RTE_LIBRTE_BITRATE) += -lrte_bitratestats > > > _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += -lrte_pmd_bond > -- > 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [PATCH v7 3/6] lib: add bitrate statistics library 2017-01-17 11:16 ` Van Haaren, Harry @ 2017-01-17 15:37 ` Remy Horton 0 siblings, 0 replies; 115+ messages in thread From: Remy Horton @ 2017-01-17 15:37 UTC (permalink / raw) To: Van Haaren, Harry, dev; +Cc: Thomas Monjalon On 17/01/2017 11:16, Van Haaren, Harry wrote: [..] >> +struct rte_stats_bitrates_s * >> +rte_stats_bitrate_create(void) >> +{ >> + return rte_zmalloc(NULL, sizeof(struct rte_stats_bitrates_s), >> + RTE_CACHE_LINE_SIZE); >> +} > > Is the socket relevant here? Perhaps pass socket_id to the function, > and use rte_zmalloc_socket(). This function has no way of > initializing bitrate structs on two different sockets, using one a > single setup thread. Not an issue in this case. It is expected that the thread that calls this creator will also be the thread that clocks the library (i.e. calling rte_stats_bitrate_calc()), and that one instance handles all ports. The memory block is not accessed outside of rte_stats_bitrate_calc(). >> + /* The +-50 fixes integer rounding during divison */ >> + if (delta > 0) >> + delta = (delta * alpha_percent + 50) / 100; >> + else >> + delta = (delta * alpha_percent - 50) / 100; >> + port_data->ewma_ibits += delta; > > The integer +50 feels a bit odd, I'm not opposed to this if it works though. It was based on feedback regarding roundoffs when doing integer divides. Something about rounding to nearest integer rather than towards zero if I remember correctly.. >> +/** >> + * Bitrate statistics data structure. >> + * This data structure is intentionally opaque. >> + */ >> +struct rte_stats_bitrates_s; > > _s question as previously highlighted. Since this is a public structure, removed the _s prefix in this case. Looking over the coding guidelines I can't see anything explicitly against the notation, but existing structures have not used it. ..Remy ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v7 4/6] app/test-pmd: add bitrate statistics calculation 2017-01-16 16:19 ` [dpdk-dev] [PATCH v7 0/6] " Remy Horton ` (2 preceding siblings ...) 2017-01-16 16:19 ` [dpdk-dev] [PATCH v7 3/6] lib: add bitrate statistics library Remy Horton @ 2017-01-16 16:19 ` Remy Horton 2017-01-17 11:19 ` Van Haaren, Harry 2017-01-16 16:19 ` [dpdk-dev] [PATCH v7 5/6] lib: added new library for latency stats Remy Horton ` (2 subsequent siblings) 6 siblings, 1 reply; 115+ messages in thread From: Remy Horton @ 2017-01-16 16:19 UTC (permalink / raw) To: dev; +Cc: Thomas Monjalon Calculate bitrate statistics using the bitrate stats library. The resulting statistics can be viewed via proc_info. Signed-off-by: Remy Horton <remy.horton@intel.com> --- app/test-pmd/testpmd.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c index bfb2f8e..a0b7430 100644 --- a/app/test-pmd/testpmd.c +++ b/app/test-pmd/testpmd.c @@ -79,6 +79,10 @@ #include <rte_pdump.h> #endif #include <rte_flow.h> +#include <rte_metrics.h> +#ifdef RTE_LIBRTE_BITRATE +#include <rte_bitrate.h> +#endif #include "testpmd.h" @@ -323,6 +327,9 @@ uint16_t nb_rx_queue_stats_mappings = 0; unsigned max_socket = 0; +/* Bitrate statistics */ +struct rte_stats_bitrates_s *bitrate_data; + /* Forward function declarations */ static void map_port_queue_stats_mapping_registers(uint8_t pi, struct rte_port *port); static void check_all_ports_link_status(uint32_t port_mask); @@ -922,12 +929,32 @@ run_pkt_fwd_on_lcore(struct fwd_lcore *fc, packet_fwd_t pkt_fwd) struct fwd_stream **fsm; streamid_t nb_fs; streamid_t sm_id; +#ifdef RTE_LIBRTE_BITRATE + uint64_t tics_per_1sec; + uint64_t tics_datum; + uint64_t tics_current; + uint8_t idx_port, cnt_ports; +#endif +#ifdef RTE_LIBRTE_BITRATE + cnt_ports = rte_eth_dev_count(); + tics_datum = rte_rdtsc(); + tics_per_1sec = rte_get_timer_hz(); +#endif fsm = &fwd_streams[fc->stream_idx]; nb_fs = fc->stream_nb; do { for (sm_id = 0; sm_id < nb_fs; sm_id++) (*pkt_fwd)(fsm[sm_id]); +#ifdef RTE_LIBRTE_BITRATE + tics_current = rte_rdtsc(); + if (tics_current - tics_datum >= tics_per_1sec) { + /* Periodic bitrate calculation */ + for (idx_port = 0; idx_port < cnt_ports; idx_port++) + rte_stats_bitrate_calc(bitrate_data, idx_port); + tics_datum = tics_current; + } +#endif } while (! fc->stopped); } @@ -2139,6 +2166,15 @@ main(int argc, char** argv) FOREACH_PORT(port_id, ports) rte_eth_promiscuous_enable(port_id); + /* Setup bitrate stats */ +#ifdef RTE_LIBRTE_BITRATE + bitrate_data = rte_stats_bitrate_create(); + if (bitrate_data == NULL) + rte_exit(EXIT_FAILURE, "Could not allocate bitrate data.\n"); + rte_stats_bitrate_reg(bitrate_data); +#endif + + #ifdef RTE_LIBRTE_CMDLINE if (interactive == 1) { if (auto_start) { -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [PATCH v7 4/6] app/test-pmd: add bitrate statistics calculation 2017-01-16 16:19 ` [dpdk-dev] [PATCH v7 4/6] app/test-pmd: add bitrate statistics calculation Remy Horton @ 2017-01-17 11:19 ` Van Haaren, Harry 0 siblings, 0 replies; 115+ messages in thread From: Van Haaren, Harry @ 2017-01-17 11:19 UTC (permalink / raw) To: Horton, Remy, dev; +Cc: Thomas Monjalon > -----Original Message----- > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Remy Horton > Sent: Monday, January 16, 2017 4:20 PM > To: dev@dpdk.org > Cc: Thomas Monjalon <thomas.monjalon@6wind.com> > Subject: [dpdk-dev] [PATCH v7 4/6] app/test-pmd: add bitrate statistics calculation > > Calculate bitrate statistics using the bitrate stats library. The > resulting statistics can be viewed via proc_info. > > Signed-off-by: Remy Horton <remy.horton@intel.com> Inline > --- > app/test-pmd/testpmd.c | 36 ++++++++++++++++++++++++++++++++++++ > 1 file changed, 36 insertions(+) > License year update, 2016 to 2017. Rest of changes looks good to me. > diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c > index bfb2f8e..a0b7430 100644 > --- a/app/test-pmd/testpmd.c > +++ b/app/test-pmd/testpmd.c > @@ -79,6 +79,10 @@ > #include <rte_pdump.h> > #endif > #include <rte_flow.h> > +#include <rte_metrics.h> > +#ifdef RTE_LIBRTE_BITRATE > +#include <rte_bitrate.h> > +#endif > > #include "testpmd.h" > > @@ -323,6 +327,9 @@ uint16_t nb_rx_queue_stats_mappings = 0; > > unsigned max_socket = 0; > > +/* Bitrate statistics */ > +struct rte_stats_bitrates_s *bitrate_data; > + > /* Forward function declarations */ > static void map_port_queue_stats_mapping_registers(uint8_t pi, struct rte_port *port); > static void check_all_ports_link_status(uint32_t port_mask); > @@ -922,12 +929,32 @@ run_pkt_fwd_on_lcore(struct fwd_lcore *fc, packet_fwd_t pkt_fwd) > struct fwd_stream **fsm; > streamid_t nb_fs; > streamid_t sm_id; > +#ifdef RTE_LIBRTE_BITRATE > + uint64_t tics_per_1sec; > + uint64_t tics_datum; > + uint64_t tics_current; > + uint8_t idx_port, cnt_ports; > +#endif > > +#ifdef RTE_LIBRTE_BITRATE > + cnt_ports = rte_eth_dev_count(); > + tics_datum = rte_rdtsc(); > + tics_per_1sec = rte_get_timer_hz(); > +#endif > fsm = &fwd_streams[fc->stream_idx]; > nb_fs = fc->stream_nb; > do { > for (sm_id = 0; sm_id < nb_fs; sm_id++) > (*pkt_fwd)(fsm[sm_id]); > +#ifdef RTE_LIBRTE_BITRATE > + tics_current = rte_rdtsc(); > + if (tics_current - tics_datum >= tics_per_1sec) { > + /* Periodic bitrate calculation */ > + for (idx_port = 0; idx_port < cnt_ports; idx_port++) > + rte_stats_bitrate_calc(bitrate_data, idx_port); > + tics_datum = tics_current; > + } > +#endif > } while (! fc->stopped); > } > > @@ -2139,6 +2166,15 @@ main(int argc, char** argv) > FOREACH_PORT(port_id, ports) > rte_eth_promiscuous_enable(port_id); > > + /* Setup bitrate stats */ > +#ifdef RTE_LIBRTE_BITRATE > + bitrate_data = rte_stats_bitrate_create(); > + if (bitrate_data == NULL) > + rte_exit(EXIT_FAILURE, "Could not allocate bitrate data.\n"); > + rte_stats_bitrate_reg(bitrate_data); > +#endif > + > + > #ifdef RTE_LIBRTE_CMDLINE > if (interactive == 1) { > if (auto_start) { > -- > 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v7 5/6] lib: added new library for latency stats 2017-01-16 16:19 ` [dpdk-dev] [PATCH v7 0/6] " Remy Horton ` (3 preceding siblings ...) 2017-01-16 16:19 ` [dpdk-dev] [PATCH v7 4/6] app/test-pmd: add bitrate statistics calculation Remy Horton @ 2017-01-16 16:19 ` Remy Horton 2017-01-17 4:29 ` Jerin Jacob 2017-01-17 11:41 ` Van Haaren, Harry 2017-01-16 16:19 ` [dpdk-dev] [PATCH v7 6/6] app/test-pmd: add latency statistics calculation Remy Horton 2017-01-17 23:24 ` [dpdk-dev] [PATCH v8 0/7] Expanded statistics reporting Remy Horton 6 siblings, 2 replies; 115+ messages in thread From: Remy Horton @ 2017-01-16 16:19 UTC (permalink / raw) To: dev; +Cc: Reshma Pattan, Thomas Monjalon From: Reshma Pattan <reshma.pattan@intel.com> Add a library designed to calculate latency statistics and report them to the application when queried. The library measures minimum, average and maximum latencies, and jitter in nano seconds. The current implementation supports global latency stats, i.e. per application stats. Signed-off-by: Reshma Pattan <reshma.pattan@intel.com> Signed-off-by: Remy Horton <remy.horton@intel.com> --- MAINTAINERS | 4 + config/common_base | 5 + doc/api/doxy-api-index.md | 1 + doc/api/doxy-api.conf | 1 + doc/guides/rel_notes/release_17_02.rst | 5 + lib/Makefile | 1 + lib/librte_latencystats/Makefile | 57 +++ lib/librte_latencystats/rte_latencystats.c | 389 +++++++++++++++++++++ lib/librte_latencystats/rte_latencystats.h | 146 ++++++++ .../rte_latencystats_version.map | 10 + lib/librte_mbuf/rte_mbuf.h | 3 + mk/rte.app.mk | 2 +- 12 files changed, 623 insertions(+), 1 deletion(-) create mode 100644 lib/librte_latencystats/Makefile create mode 100644 lib/librte_latencystats/rte_latencystats.c create mode 100644 lib/librte_latencystats/rte_latencystats.h create mode 100644 lib/librte_latencystats/rte_latencystats_version.map diff --git a/MAINTAINERS b/MAINTAINERS index 6cd9896..0a41fe5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -714,3 +714,7 @@ F: examples/tep_termination/ F: examples/vmdq/ F: examples/vmdq_dcb/ F: doc/guides/sample_app_ug/vmdq_dcb_forwarding.rst + +Latency Stats +M: Reshma Pattan <reshma.pattan@intel.com> +F: lib/librte_latencystats/ diff --git a/config/common_base b/config/common_base index decebe5..762a54c 100644 --- a/config/common_base +++ b/config/common_base @@ -603,3 +603,8 @@ CONFIG_RTE_LIBRTE_METRICS=y # Compile the bitrate statistics library # CONFIG_RTE_LIBRTE_BITRATE=y + +# +# Compile the latency statistics library +# +CONFIG_RTE_LIBRTE_LATENCY_STATS=y diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md index 5e194b0..1cacacc 100644 --- a/doc/api/doxy-api-index.md +++ b/doc/api/doxy-api-index.md @@ -152,4 +152,5 @@ There are many libraries, so their headers may be grouped by topics: [keepalive] (@ref rte_keepalive.h), [Device Metrics] (@ref rte_metrics.h), [Bitrate Statistics] (@ref rte_bitrate.h), + [Latency stats] (@ref rte_latencystats.h), [version] (@ref rte_version.h) diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf index 6e6ab5c..0effece 100644 --- a/doc/api/doxy-api.conf +++ b/doc/api/doxy-api.conf @@ -47,6 +47,7 @@ INPUT = doc/api/doxy-api-index.md \ lib/librte_jobstats \ lib/librte_kni \ lib/librte_kvargs \ + lib/librte_latencystats \ lib/librte_lpm \ lib/librte_mbuf \ lib/librte_mempool \ diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst index 44012c8..c09e60b 100644 --- a/doc/guides/rel_notes/release_17_02.rst +++ b/doc/guides/rel_notes/release_17_02.rst @@ -68,6 +68,10 @@ New Features Six new APIs have been added to the ixgbe PMD for MACsec offload support. The declarations for the APIs can be found in ``rte_pmd_ixgbe.h``. +* **Added latency stats library.** + A library that facilitates latency stats measurment of the dpdk based + applications. The library measures minimum, average, maximum latencies + and also jitter in nano seconds. Resolved Issues --------------- @@ -184,6 +188,7 @@ The libraries prepended with a plus sign were incremented in this version. librte_jobstats.so.1 librte_kni.so.2 librte_kvargs.so.1 + + librte_latencystats.so.1 librte_lpm.so.2 librte_mbuf.so.2 librte_mempool.so.2 diff --git a/lib/Makefile b/lib/Makefile index e211bc0..6fffa88 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -60,6 +60,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics DIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += librte_bitratestats +DIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += librte_latencystats ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni diff --git a/lib/librte_latencystats/Makefile b/lib/librte_latencystats/Makefile new file mode 100644 index 0000000..f744da6 --- /dev/null +++ b/lib/librte_latencystats/Makefile @@ -0,0 +1,57 @@ +# BSD LICENSE +# +# Copyright(c) 2016 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +include $(RTE_SDK)/mk/rte.vars.mk + +# library name +LIB = librte_latencystats.a + +CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3 +LDLIBS += -lm +LDLIBS += -lpthread + +EXPORT_MAP := rte_latencystats_version.map + +LIBABIVER := 1 + +# all source are stored in SRCS-y +SRCS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) := rte_latencystats.c + +# install this header file +SYMLINK-$(CONFIG_RTE_LIBRTE_LATENCY_STATS)-include := rte_latencystats.h + +# this lib depends upon: +DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_mbuf +DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_eal +DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_ether +DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_metrics + +include $(RTE_SDK)/mk/rte.lib.mk diff --git a/lib/librte_latencystats/rte_latencystats.c b/lib/librte_latencystats/rte_latencystats.c new file mode 100644 index 0000000..1a68469 --- /dev/null +++ b/lib/librte_latencystats/rte_latencystats.c @@ -0,0 +1,389 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <unistd.h> +#include <sys/types.h> +#include <stdbool.h> +#include <math.h> +#include <pthread.h> + +#include <rte_mbuf.h> +#include <rte_log.h> +#include <rte_cycles.h> +#include <rte_ethdev.h> +#include <rte_metrics.h> +#include <rte_memzone.h> +#include <rte_lcore.h> +#include <rte_timer.h> + +#include "rte_latencystats.h" + +/** Nano seconds per second */ +#define NS_PER_SEC 1E9 + +/** Clock cycles per nano second */ +#define CYCLES_PER_NS (rte_get_timer_hz() / NS_PER_SEC) + +/* Macros for printing using RTE_LOG */ +#define RTE_LOGTYPE_LATENCY_STATS RTE_LOGTYPE_USER1 + +static pthread_t latency_stats_thread; +static const char *MZ_RTE_LATENCY_STATS = "rte_latencystats"; +static int latency_stats_index; +static uint64_t samp_intvl; +static uint64_t timer_tsc; +static uint64_t prev_tsc; + +static struct rte_latency_stats { + float min_latency; /**< Minimum latency in nano seconds */ + float avg_latency; /**< Average latency in nano seconds */ + float max_latency; /**< Maximum latency in nano seconds */ + float jitter; /** Latency variation */ +} *glob_stats; + +static struct rxtx_cbs { + struct rte_eth_rxtx_callback *cb; +} rx_cbs[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT], + tx_cbs[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT]; + +struct latency_stats_nameoff { + char name[RTE_ETH_XSTATS_NAME_SIZE]; + unsigned int offset; +}; + +static const struct latency_stats_nameoff lat_stats_strings[] = { + {"min_latency_ns", offsetof(struct rte_latency_stats, min_latency)}, + {"avg_latency_ns", offsetof(struct rte_latency_stats, avg_latency)}, + {"max_latency_ns", offsetof(struct rte_latency_stats, max_latency)}, + {"jitter_ns", offsetof(struct rte_latency_stats, jitter)}, +}; + +#define NUM_LATENCY_STATS (sizeof(lat_stats_strings) / \ + sizeof(lat_stats_strings[0])) + +static __attribute__((noreturn)) void * +report_latency_stats(__rte_unused void *arg) +{ + for (;;) { + unsigned int i; + float *stats_ptr = NULL; + uint64_t values[NUM_LATENCY_STATS] = {0}; + int ret; + + for (i = 0; i < NUM_LATENCY_STATS; i++) { + stats_ptr = RTE_PTR_ADD(glob_stats, + lat_stats_strings[i].offset); + values[i] = (uint64_t)floor((*stats_ptr)/ + CYCLES_PER_NS); + } + + ret = rte_metrics_update_metrics(RTE_METRICS_GLOBAL, + latency_stats_index, + values, NUM_LATENCY_STATS); + if (ret < 0) + RTE_LOG(INFO, LATENCY_STATS, + "Failed to push the stats\n"); + } +} + +static void +rte_latencystats_fill_values(struct rte_metric_value *values) +{ + unsigned int i; + float *stats_ptr = NULL; + + for (i = 0; i < NUM_LATENCY_STATS; i++) { + stats_ptr = RTE_PTR_ADD(glob_stats, + lat_stats_strings[i].offset); + values[i].key = i; + values[i].value = (uint64_t)floor((*stats_ptr)/ + CYCLES_PER_NS); + } +} + +static uint16_t +add_time_stamps(uint8_t pid __rte_unused, + uint16_t qid __rte_unused, + struct rte_mbuf **pkts, + uint16_t nb_pkts, + uint16_t max_pkts __rte_unused, + void *user_cb __rte_unused) +{ + unsigned int i; + uint64_t diff_tsc, now; + + /* + * For every sample interval, + * time stamp is marked on one received packet. + */ + now = rte_rdtsc(); + for (i = 0; i < nb_pkts; i++) { + diff_tsc = now - prev_tsc; + timer_tsc += diff_tsc; + if (timer_tsc >= samp_intvl) { + /* + * TBD: Mark the timestamp only + * if not already marked by the + * hardware or the PMD. + */ + pkts[i]->timestamp = now; + timer_tsc = 0; + } + prev_tsc = now; + now = rte_rdtsc(); + } + + return nb_pkts; +} + +static uint16_t +calc_latency(uint8_t pid __rte_unused, + uint16_t qid __rte_unused, + struct rte_mbuf **pkts, + uint16_t nb_pkts, + void *_ __rte_unused) +{ + unsigned int i, cnt = 0; + uint64_t now; + float latency[nb_pkts]; + static float prev_latency; + /* + * Alpha represents degree of weighting decrease in EWMA, + * a constant smoothing factor between 0 and 1. The value + * is used below for measuring average latency. + */ + const float alpha = 0.2; + + now = rte_rdtsc(); + for (i = 0; i < nb_pkts; i++) { + if (pkts[i]->timestamp) + latency[cnt++] = now - pkts[i]->timestamp; + } + + for (i = 0; i < cnt; i++) { + /* + * The jitter is calculated as statistical mean of interpacket + * delay variation. The "jitter estimate" is computed by taking + * the absolute values of the ipdv sequence and applying an + * exponential filter with parameter 1/16 to generate the + * estimate. i.e J=J+(|D(i-1,i)|-J)/16. Where J is jitter, + * D(i-1,i) is difference in latency of two consecutive packets + * i-1 and i. + * Reference: Calculated as per RFC 5481, sec 4.1, + * RFC 3393 sec 4.5, RFC 1889 sec. + */ + glob_stats->jitter += (abs(prev_latency - latency[i]) + - glob_stats->jitter)/16; + if (glob_stats->min_latency == 0) + glob_stats->min_latency = latency[i]; + else if (latency[i] < glob_stats->min_latency) + glob_stats->min_latency = latency[i]; + else if (latency[i] > glob_stats->max_latency) + glob_stats->max_latency = latency[i]; + /* + * The average latency is measured using exponential moving + * average, i.e. using EWMA + * https://en.wikipedia.org/wiki/Moving_average + */ + glob_stats->avg_latency += + alpha * (latency[i] - glob_stats->avg_latency); + prev_latency = latency[i]; + } + + return nb_pkts; +} + +int +rte_latencystats_init(uint64_t samp_intvl, + rte_latency_stats_flow_type_fn user_cb) +{ + unsigned int i; + uint8_t pid; + uint16_t qid; + struct rxtx_cbs *cbs = NULL; + const uint8_t nb_ports = rte_eth_dev_count(); + const char *ptr_strings[NUM_LATENCY_STATS] = {0}; + const struct rte_memzone *mz = NULL; + const unsigned int flags = 0; + + /** Allocate stats in shared memory fo muliti process support */ + mz = rte_memzone_reserve(MZ_RTE_LATENCY_STATS, sizeof(*glob_stats), + rte_socket_id(), flags); + if (mz == NULL) { + RTE_LOG(ERR, LATENCY_STATS, "Cannot reserve memory: %s:%d\n", + __func__, __LINE__); + return -ENOMEM; + } + + glob_stats = mz->addr; + samp_intvl *= CYCLES_PER_NS; + + /** Register latency stats with stats library */ + for (i = 0; i < NUM_LATENCY_STATS; i++) + ptr_strings[i] = lat_stats_strings[i].name; + + latency_stats_index = rte_metrics_reg_metrics(ptr_strings, + NUM_LATENCY_STATS); + if (latency_stats_index < 0) { + RTE_LOG(DEBUG, LATENCY_STATS, + "Failed to register latency stats names\n"); + return -1; + } + + /** Register Rx/Tx callbacks */ + for (pid = 0; pid < nb_ports; pid++) { + struct rte_eth_dev_info dev_info; + rte_eth_dev_info_get(pid, &dev_info); + for (qid = 0; qid < dev_info.nb_rx_queues; qid++) { + cbs = &rx_cbs[pid][qid]; + cbs->cb = rte_eth_add_first_rx_callback(pid, qid, + add_time_stamps, user_cb); + if (!cbs->cb) + RTE_LOG(INFO, LATENCY_STATS, "Failed to " + "register Rx callback for pid=%d, " + "qid=%d\n", pid, qid); + } + for (qid = 0; qid < dev_info.nb_tx_queues; qid++) { + cbs = &tx_cbs[pid][qid]; + cbs->cb = rte_eth_add_tx_callback(pid, qid, + calc_latency, user_cb); + if (!cbs->cb) + RTE_LOG(INFO, LATENCY_STATS, "Failed to " + "register Tx callback for pid=%d, " + "qid=%d\n", pid, qid); + } + } + + int ret = 0; + char thread_name[RTE_MAX_THREAD_NAME_LEN]; + + /** Create the host thread to update latency stats to stats library */ + ret = pthread_create(&latency_stats_thread, NULL, report_latency_stats, + NULL); + if (ret != 0) { + RTE_LOG(ERR, LATENCY_STATS, + "Failed to create the latency stats thread:%s, %s:%d\n", + strerror(errno), __func__, __LINE__); + return -1; + } + /** Set thread_name for aid in debugging */ + snprintf(thread_name, RTE_MAX_THREAD_NAME_LEN, "latency-stats-thread"); + ret = rte_thread_setname(latency_stats_thread, thread_name); + if (ret != 0) + RTE_LOG(DEBUG, LATENCY_STATS, + "Failed to set thread name for latency stats handling\n"); + + return 0; +} + +int +rte_latencystats_uninit(void) +{ + uint8_t pid; + uint16_t qid; + int ret = 0; + struct rxtx_cbs *cbs = NULL; + const uint8_t nb_ports = rte_eth_dev_count(); + + /** De register Rx/Tx callbacks */ + for (pid = 0; pid < nb_ports; pid++) { + struct rte_eth_dev_info dev_info; + rte_eth_dev_info_get(pid, &dev_info); + for (qid = 0; qid < dev_info.nb_rx_queues; qid++) { + cbs = &rx_cbs[pid][qid]; + ret = rte_eth_remove_rx_callback(pid, qid, cbs->cb); + if (ret) + RTE_LOG(INFO, LATENCY_STATS, "failed to " + "remove Rx callback for pid=%d, " + "qid=%d\n", pid, qid); + } + for (qid = 0; qid < dev_info.nb_tx_queues; qid++) { + cbs = &tx_cbs[pid][qid]; + ret = rte_eth_remove_tx_callback(pid, qid, cbs->cb); + if (ret) + RTE_LOG(INFO, LATENCY_STATS, "failed to " + "remove Tx callback for pid=%d, " + "qid=%d\n", pid, qid); + } + } + + /** Cancel the thread */ + ret = pthread_cancel(latency_stats_thread); + if (ret != 0) { + RTE_LOG(ERR, LATENCY_STATS, + "Failed to cancel latency stats update thread:" + "%s,%s:%d\n", + strerror(errno), __func__, __LINE__); + return -1; + } + + return 0; +} + +int +rte_latencystats_get_names(struct rte_metric_name *names, uint16_t size) +{ + unsigned int i; + + if (names == NULL || size < NUM_LATENCY_STATS) + return NUM_LATENCY_STATS; + + for (i = 0; i < NUM_LATENCY_STATS; i++) + snprintf(names[i].name, sizeof(names[i].name), + "%s", lat_stats_strings[i].name); + + return NUM_LATENCY_STATS; +} + +int +rte_latencystats_get(struct rte_metric_value *values, uint16_t size) +{ + if (size < NUM_LATENCY_STATS || values == NULL) + return NUM_LATENCY_STATS; + + if (rte_eal_process_type() == RTE_PROC_SECONDARY) { + const struct rte_memzone *mz; + mz = rte_memzone_lookup(MZ_RTE_LATENCY_STATS); + if (mz == NULL) { + RTE_LOG(ERR, LATENCY_STATS, + "Latency stats memzone not found\n"); + return -ENOMEM; + } + glob_stats = mz->addr; + } + + /* Retrieve latency stats */ + rte_latencystats_fill_values(values); + + return NUM_LATENCY_STATS; +} diff --git a/lib/librte_latencystats/rte_latencystats.h b/lib/librte_latencystats/rte_latencystats.h new file mode 100644 index 0000000..405b878 --- /dev/null +++ b/lib/librte_latencystats/rte_latencystats.h @@ -0,0 +1,146 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _RTE_LATENCYSTATS_H_ +#define _RTE_LATENCYSTATS_H_ + +/** + * @file + * RTE latency stats + * + * library to provide application and flow based latency stats. + */ + +#include <rte_metrics.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Note: This function pointer is for future flow based latency stats + * implementation. + * + * Function type used for identifting flow types of a Rx packet. + * + * The callback function is called on Rx for each packet. + * This function is used for flow based latency calculations. + * + * @param pkt + * Packet that has to be identified with its flow types. + * @param user_param + * The arbitrary user parameter passed in by the application when + * the callback was originally configured. + * @return + * The flow_mask, representing the multiple flow types of a packet. + */ +typedef uint16_t (*rte_latency_stats_flow_type_fn)(struct rte_mbuf *pkt, + void *user_param); + +/** + * Registers Rx/Tx callbacks for each active port, queue. + * + * @param samp_intvl + * Sampling time period in nano seconds, at which packet + * should be marked with time stamp. + * @param user_cb + * Note: This param is for future flow based latency stats + * implementation. + * User callback to be called to get flow types of a packet. + * Used for flow based latency calculation. + * If the value is NULL, global stats will be calculated, + * else flow based latency stats will be calculated. + * For now just pass on the NULL value to this param. + * @return + * -1 : On error + * -ENOMEM: On error + * 0 : On success + */ +int rte_latencystats_init(uint64_t samp_intvl, + rte_latency_stats_flow_type_fn user_cb); + +/** + * Removes registered Rx/Tx callbacks for each active port, queue. + * + * @return + * -1: On error + * 0: On success + */ +int rte_latencystats_uninit(void); + +/** + * Retrieve names of latency statistics + * + * @param names + * Block of memory to insert names into. Must be at least size in capacity. + * If set to NULL, function returns required capacity. + * @param size + * Capacity of latency stats names (number of names). + * @return + * - positive value lower or equal to size: success. The return value + * is the number of entries filled in the stats table. + * - positive value higher than size: error, the given statistics table + * is too small. The return value corresponds to the size that should + * be given to succeed. The entries in the table are not valid and + * shall not be used by the caller. + */ +int rte_latencystats_get_names(struct rte_metric_name *names, + uint16_t size); + +/** + * Retrieve latency statistics. + * + * @param values + * A pointer to a table of structure of type *rte_metric_value* + * to be filled with latency statistics ids and values. + * This parameter can be set to NULL if size is 0. + * @param size + * The size of the stats table, which should be large enough to store + * all the latency stats. + * @return + * - positive value lower or equal to size: success. The return value + * is the number of entries filled in the stats table. + * - positive value higher than size: error, the given statistics table + * is too small. The return value corresponds to the size that should + * be given to succeed. The entries in the table are not valid and + * shall not be used by the caller. + * -ENOMEM: On failure. + */ +int rte_latencystats_get(struct rte_metric_value *values, + uint16_t size); + +#ifdef __cplusplus +} +#endif + +#endif /* _RTE_LATENCYSTATS_H_ */ diff --git a/lib/librte_latencystats/rte_latencystats_version.map b/lib/librte_latencystats/rte_latencystats_version.map new file mode 100644 index 0000000..502018e --- /dev/null +++ b/lib/librte_latencystats/rte_latencystats_version.map @@ -0,0 +1,10 @@ +DPDK_17.02 { + global: + + rte_latencystats_get; + rte_latencystats_get_names; + rte_latencystats_init; + rte_latencystats_uninit; + + local: *; +}; diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h index bfce9f4..c35ba0a 100644 --- a/lib/librte_mbuf/rte_mbuf.h +++ b/lib/librte_mbuf/rte_mbuf.h @@ -512,6 +512,9 @@ struct rte_mbuf { /** Timesync flags for use with IEEE1588. */ uint16_t timesync; + + /** Timestamp for measuring latency. */ + uint64_t timestamp; } __rte_cache_aligned; /** diff --git a/mk/rte.app.mk b/mk/rte.app.mk index 6aac5ac..1d36fad 100644 --- a/mk/rte.app.mk +++ b/mk/rte.app.mk @@ -100,7 +100,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE) += -lrte_cmdline _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE) += -lrte_cfgfile _LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS) += -lrte_metrics _LDLIBS-$(CONFIG_RTE_LIBRTE_BITRATE) += -lrte_bitratestats - +_LDLIBS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += -lrte_latencystats _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += -lrte_pmd_bond _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += -lrte_pmd_xenvirt -lxenstore -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [PATCH v7 5/6] lib: added new library for latency stats 2017-01-16 16:19 ` [dpdk-dev] [PATCH v7 5/6] lib: added new library for latency stats Remy Horton @ 2017-01-17 4:29 ` Jerin Jacob 2017-01-17 6:48 ` Remy Horton 2017-01-17 11:19 ` Mcnamara, John 2017-01-17 11:41 ` Van Haaren, Harry 1 sibling, 2 replies; 115+ messages in thread From: Jerin Jacob @ 2017-01-17 4:29 UTC (permalink / raw) To: Remy Horton; +Cc: dev, Reshma Pattan, Thomas Monjalon On Mon, Jan 16, 2017 at 04:19:32PM +0000, Remy Horton wrote: > From: Reshma Pattan <reshma.pattan@intel.com> > > Add a library designed to calculate latency statistics and report them > to the application when queried. The library measures minimum, average and > maximum latencies, and jitter in nano seconds. The current implementation > supports global latency stats, i.e. per application stats. > > Signed-off-by: Reshma Pattan <reshma.pattan@intel.com> > Signed-off-by: Remy Horton <remy.horton@intel.com> > --- > MAINTAINERS | 4 + > config/common_base | 5 + > doc/api/doxy-api-index.md | 1 + > doc/api/doxy-api.conf | 1 + > doc/guides/rel_notes/release_17_02.rst | 5 + > lib/Makefile | 1 + > lib/librte_latencystats/Makefile | 57 +++ > lib/librte_latencystats/rte_latencystats.c | 389 +++++++++++++++++++++ > lib/librte_latencystats/rte_latencystats.h | 146 ++++++++ > .../rte_latencystats_version.map | 10 + > lib/librte_mbuf/rte_mbuf.h | 3 + It is a value added feature for DPDK. But what is the plan for incorporating the mbuf change? I have 8 month old mbuf change for ARM for natural alignment. If we are accepting any mbuf change then we need to include outstanding mbuf changes to avoid future ABI breakage. http://dpdk.org/dev/patchwork/patch/12878/ Jerin ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [PATCH v7 5/6] lib: added new library for latency stats 2017-01-17 4:29 ` Jerin Jacob @ 2017-01-17 6:48 ` Remy Horton 2017-01-17 7:35 ` Jerin Jacob 2017-01-17 11:19 ` Mcnamara, John 1 sibling, 1 reply; 115+ messages in thread From: Remy Horton @ 2017-01-17 6:48 UTC (permalink / raw) To: Jerin Jacob; +Cc: dev, Reshma Pattan, Thomas Monjalon On 17/01/2017 04:29, Jerin Jacob wrote: [..] > It is a value added feature for DPDK. But what is the plan for incorporating > the mbuf change? I have 8 month old mbuf change for ARM for natural > alignment. If we are accepting any mbuf change then we need to include > outstanding mbuf changes to avoid future ABI breakage. > > http://dpdk.org/dev/patchwork/patch/12878/ I know there's some discussion going on in the background regarding this. I've yet to hear a definite answer myself.. ..Remy ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [PATCH v7 5/6] lib: added new library for latency stats 2017-01-17 6:48 ` Remy Horton @ 2017-01-17 7:35 ` Jerin Jacob 0 siblings, 0 replies; 115+ messages in thread From: Jerin Jacob @ 2017-01-17 7:35 UTC (permalink / raw) To: Remy Horton; +Cc: dev, Reshma Pattan, Thomas Monjalon On Tue, Jan 17, 2017 at 06:48:30AM +0000, Remy Horton wrote: > > On 17/01/2017 04:29, Jerin Jacob wrote: > [..] > > It is a value added feature for DPDK. But what is the plan for incorporating > > the mbuf change? I have 8 month old mbuf change for ARM for natural > > alignment. If we are accepting any mbuf change then we need to include > > outstanding mbuf changes to avoid future ABI breakage. > > > > http://dpdk.org/dev/patchwork/patch/12878/ > > I know there's some discussion going on in the background regarding this. > I've yet to hear a definite answer myself.. This was the last thread on this topic http://dpdk.org/ml/archives/dev/2016-July/043222.html Where Oliver want to group a few of the mbuf changes together. Thats is good. But, looking at the history(holding a ARM specific patch for 8 months), I don't believe, we will get consensus on _all_ the items on mbuf change like ports, m->next etc. I think we had consensus on my change(making mbuf natural aligned), but it was queued for grouping with other mbuf changes. Jerin > > ..Remy ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [PATCH v7 5/6] lib: added new library for latency stats 2017-01-17 4:29 ` Jerin Jacob 2017-01-17 6:48 ` Remy Horton @ 2017-01-17 11:19 ` Mcnamara, John 2017-01-17 12:34 ` Jerin Jacob 1 sibling, 1 reply; 115+ messages in thread From: Mcnamara, John @ 2017-01-17 11:19 UTC (permalink / raw) To: Jerin Jacob, Horton, Remy Cc: dev, Pattan, Reshma, Thomas Monjalon, olivier.matz > -----Original Message----- > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Jerin Jacob > Sent: Tuesday, January 17, 2017 4:30 AM > To: Horton, Remy <remy.horton@intel.com> > Cc: dev@dpdk.org; Pattan, Reshma <reshma.pattan@intel.com>; Thomas > Monjalon <thomas.monjalon@6wind.com> > Subject: Re: [dpdk-dev] [PATCH v7 5/6] lib: added new library for latency > stats > > On Mon, Jan 16, 2017 at 04:19:32PM +0000, Remy Horton wrote: > > From: Reshma Pattan <reshma.pattan@intel.com> > > > > Add a library designed to calculate latency statistics and report them > > to the application when queried. The library measures minimum, average > > and maximum latencies, and jitter in nano seconds. The current > > implementation supports global latency stats, i.e. per application > stats. > > > > Signed-off-by: Reshma Pattan <reshma.pattan@intel.com> > > Signed-off-by: Remy Horton <remy.horton@intel.com> > > --- > > MAINTAINERS | 4 + > > config/common_base | 5 + > > doc/api/doxy-api-index.md | 1 + > > doc/api/doxy-api.conf | 1 + > > doc/guides/rel_notes/release_17_02.rst | 5 + > > lib/Makefile | 1 + > > lib/librte_latencystats/Makefile | 57 +++ > > lib/librte_latencystats/rte_latencystats.c | 389 > +++++++++++++++++++++ > > lib/librte_latencystats/rte_latencystats.h | 146 ++++++++ > > .../rte_latencystats_version.map | 10 + > > lib/librte_mbuf/rte_mbuf.h | 3 + > > It is a value added feature for DPDK. But what is the plan for > incorporating the mbuf change? I have 8 month old mbuf change for ARM for > natural alignment. If we are accepting any mbuf change then we need to > include outstanding mbuf changes to avoid future ABI breakage. > > http://dpdk.org/dev/patchwork/patch/12878/ > Hi Jerin, As far as I know the plan was to reach some sort of consensus on the mbuf structure at the DPDK Userspace 2016, during and after Olivier's presentation and then to make those changes during 17.02. However, I believe Olivier had other work commitments in this release and wasn't able to work on the mbuf changes. The above mbuf change (and addition at the end of the struct) should have gone into that mbuf rework, along with your changes. However, since the mbuf rework didn't happen we need to add the field in this release. I guess the difference between the above change and your change is that the latter is more complex and potentially affect performance, and as such makes more sense as part of a rework. Perhaps we, as a community, should commit to the mbuf rework in 17.05 and make sure it gets done. John ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [PATCH v7 5/6] lib: added new library for latency stats 2017-01-17 11:19 ` Mcnamara, John @ 2017-01-17 12:34 ` Jerin Jacob 2017-01-17 14:53 ` Mcnamara, John 0 siblings, 1 reply; 115+ messages in thread From: Jerin Jacob @ 2017-01-17 12:34 UTC (permalink / raw) To: Mcnamara, John Cc: Horton, Remy, dev, Pattan, Reshma, Thomas Monjalon, olivier.matz On Tue, Jan 17, 2017 at 11:19:24AM +0000, Mcnamara, John wrote: > > -----Original Message----- > > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Jerin Jacob > > Sent: Tuesday, January 17, 2017 4:30 AM > > To: Horton, Remy <remy.horton@intel.com> > > Cc: dev@dpdk.org; Pattan, Reshma <reshma.pattan@intel.com>; Thomas > > Monjalon <thomas.monjalon@6wind.com> > > Subject: Re: [dpdk-dev] [PATCH v7 5/6] lib: added new library for latency > > stats > > > > On Mon, Jan 16, 2017 at 04:19:32PM +0000, Remy Horton wrote: > > > From: Reshma Pattan <reshma.pattan@intel.com> > > > > > > Add a library designed to calculate latency statistics and report them > > > to the application when queried. The library measures minimum, average > > > and maximum latencies, and jitter in nano seconds. The current > > > implementation supports global latency stats, i.e. per application > > stats. > > > > > > Signed-off-by: Reshma Pattan <reshma.pattan@intel.com> > > > Signed-off-by: Remy Horton <remy.horton@intel.com> > > > --- > > > MAINTAINERS | 4 + > > > config/common_base | 5 + > > > doc/api/doxy-api-index.md | 1 + > > > doc/api/doxy-api.conf | 1 + > > > doc/guides/rel_notes/release_17_02.rst | 5 + > > > lib/Makefile | 1 + > > > lib/librte_latencystats/Makefile | 57 +++ > > > lib/librte_latencystats/rte_latencystats.c | 389 > > +++++++++++++++++++++ > > > lib/librte_latencystats/rte_latencystats.h | 146 ++++++++ > > > .../rte_latencystats_version.map | 10 + > > > lib/librte_mbuf/rte_mbuf.h | 3 + > > > > It is a value added feature for DPDK. But what is the plan for > > incorporating the mbuf change? I have 8 month old mbuf change for ARM for > > natural alignment. If we are accepting any mbuf change then we need to > > include outstanding mbuf changes to avoid future ABI breakage. > > > > http://dpdk.org/dev/patchwork/patch/12878/ > > > > Hi Jerin, Hi John, > > As far as I know the plan was to reach some sort of consensus on the mbuf > structure at the DPDK Userspace 2016, during and after Olivier's > presentation and then to make those changes during 17.02. > > However, I believe Olivier had other work commitments in this release and > wasn't able to work on the mbuf changes. > > The above mbuf change (and addition at the end of the struct) should > have gone into that mbuf rework, along with your changes. > > However, since the mbuf rework didn't happen we need to add the field in > this release. So we don't care the mbuf ABI breakage in the next release. This wasn't the message I got earlier for ARM's mbuf change. http://dpdk.org/dev/patchwork/patch/12878/ > > I guess the difference between the above change and your change is that > the latter is more complex and potentially affect performance, and as such > makes more sense as part of a rework. The mbuf natural alignment is a not complex change, it just moving the field and it does not have any performance impact on IA nor nobody reported any performance regression on IA. There is nothing against you or this feature. The only part concerns me that some set of patches can always override any rule and include in the release (even as marking as EXPERIMENTAL) because of its important for some set of consumers. Another set has to wait in the queue because its not important for some people. For me, it is not a sign of vendor neutral open source project. Jerin > > Perhaps we, as a community, should commit to the mbuf rework in 17.05 > and make sure it gets done. > > John > > > > > > ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [PATCH v7 5/6] lib: added new library for latency stats 2017-01-17 12:34 ` Jerin Jacob @ 2017-01-17 14:53 ` Mcnamara, John 2017-01-17 16:25 ` Jerin Jacob 0 siblings, 1 reply; 115+ messages in thread From: Mcnamara, John @ 2017-01-17 14:53 UTC (permalink / raw) To: Jerin Jacob Cc: Horton, Remy, dev, Pattan, Reshma, Thomas Monjalon, olivier.matz, Richardson, Bruce > -----Original Message----- > From: Jerin Jacob [mailto:jerin.jacob@caviumnetworks.com] > Sent: Tuesday, January 17, 2017 12:34 PM > To: Mcnamara, John <john.mcnamara@intel.com> > Cc: Horton, Remy <remy.horton@intel.com>; dev@dpdk.org; Pattan, Reshma > <reshma.pattan@intel.com>; Thomas Monjalon <thomas.monjalon@6wind.com>; > olivier.matz@6wind.com > Subject: Re: [dpdk-dev] [PATCH v7 5/6] lib: added new library for latency > stats > > On Tue, Jan 17, 2017 at 11:19:24AM +0000, Mcnamara, John wrote: > > > -----Original Message----- > > > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Jerin Jacob > > > Sent: Tuesday, January 17, 2017 4:30 AM > > > To: Horton, Remy <remy.horton@intel.com> > > > Cc: dev@dpdk.org; Pattan, Reshma <reshma.pattan@intel.com>; Thomas > > > Monjalon <thomas.monjalon@6wind.com> > > > Subject: Re: [dpdk-dev] [PATCH v7 5/6] lib: added new library for > > > latency stats > > > > > > On Mon, Jan 16, 2017 at 04:19:32PM +0000, Remy Horton wrote: > > > > From: Reshma Pattan <reshma.pattan@intel.com> > > > > > > > > Add a library designed to calculate latency statistics and report > > > > them to the application when queried. The library measures > > > > minimum, average and maximum latencies, and jitter in nano > > > > seconds. The current implementation supports global latency stats, > > > > i.e. per application > > > stats. > > > > > > > > Signed-off-by: Reshma Pattan <reshma.pattan@intel.com> > > > > Signed-off-by: Remy Horton <remy.horton@intel.com> > > > > --- > > > > MAINTAINERS | 4 + > > > > config/common_base | 5 + > > > > doc/api/doxy-api-index.md | 1 + > > > > doc/api/doxy-api.conf | 1 + > > > > doc/guides/rel_notes/release_17_02.rst | 5 + > > > > lib/Makefile | 1 + > > > > lib/librte_latencystats/Makefile | 57 +++ > > > > lib/librte_latencystats/rte_latencystats.c | 389 > > > +++++++++++++++++++++ > > > > lib/librte_latencystats/rte_latencystats.h | 146 ++++++++ > > > > .../rte_latencystats_version.map | 10 + > > > > lib/librte_mbuf/rte_mbuf.h | 3 + > > > > > > It is a value added feature for DPDK. But what is the plan for > > > incorporating the mbuf change? I have 8 month old mbuf change for > > > ARM for natural alignment. If we are accepting any mbuf change then > > > we need to include outstanding mbuf changes to avoid future ABI > breakage. > > > > > > http://dpdk.org/dev/patchwork/patch/12878/ > > > > > > > Hi Jerin, > > Hi John, > > > > > As far as I know the plan was to reach some sort of consensus on the > > mbuf structure at the DPDK Userspace 2016, during and after Olivier's > > presentation and then to make those changes during 17.02. > > > > However, I believe Olivier had other work commitments in this release > > and wasn't able to work on the mbuf changes. > > > > The above mbuf change (and addition at the end of the struct) should > > have gone into that mbuf rework, along with your changes. > > > > However, since the mbuf rework didn't happen we need to add the field > > in this release. > > So we don't care the mbuf ABI breakage in the next release. This wasn't > the message I got earlier for ARM's mbuf change. > > http://dpdk.org/dev/patchwork/patch/12878/ Hi Jerin, We do care about ABI breakage but I was under the impression that the timestamp change wasn't breaking the ABI since it was at the end of the struct. I also ran the ABI validator against the change and it didn't show any breakage. http://dpdk.org/doc/guides/contributing/versioning.html#running-the-abi-validator The rearm_data alignment patch, on the other hand, does break ABI. I think that is the main difference between the two patches. If the timestamp change does break ABI then it should also wait until the mbuf restructuring. > ... > > There is nothing against you or this feature. The only part concerns me > that some set of patches can always override any rule and include in the > release (even as marking as EXPERIMENTAL) because of its important for > some set of consumers. > Another set has to wait in the queue because its not important for some > people. > For me, it is not a sign of vendor neutral open source project. To be fair I don't think we are trying to override any rule here. Also, we aren't the only vendor looking for a timestamp in the mbuf. Mellanox also submitted a patch: http://dpdk.org/ml/archives/dev/2016-October/048809.html However, it is also fair to acknowledge that the rearm_data alignment patch shouldn't have had to wait so long. I can't really answer for that directly. My feeling is that it was targeted for the mbuf rework but got forgotten when that work slipped. John ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [PATCH v7 5/6] lib: added new library for latency stats 2017-01-17 14:53 ` Mcnamara, John @ 2017-01-17 16:25 ` Jerin Jacob 2017-01-18 20:11 ` Olivier Matz 0 siblings, 1 reply; 115+ messages in thread From: Jerin Jacob @ 2017-01-17 16:25 UTC (permalink / raw) To: Mcnamara, John Cc: Horton, Remy, dev, Pattan, Reshma, Thomas Monjalon, olivier.matz, Richardson, Bruce On Tue, Jan 17, 2017 at 02:53:55PM +0000, Mcnamara, John wrote: > > > > -----Original Message----- > > From: Jerin Jacob [mailto:jerin.jacob@caviumnetworks.com] > > Sent: Tuesday, January 17, 2017 12:34 PM > > To: Mcnamara, John <john.mcnamara@intel.com> > > Cc: Horton, Remy <remy.horton@intel.com>; dev@dpdk.org; Pattan, Reshma > > <reshma.pattan@intel.com>; Thomas Monjalon <thomas.monjalon@6wind.com>; > > olivier.matz@6wind.com > > Subject: Re: [dpdk-dev] [PATCH v7 5/6] lib: added new library for latency > > stats > > > > On Tue, Jan 17, 2017 at 11:19:24AM +0000, Mcnamara, John wrote: > > > > -----Original Message----- > > > > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Jerin Jacob > > > > Sent: Tuesday, January 17, 2017 4:30 AM > > > > To: Horton, Remy <remy.horton@intel.com> > > > > Cc: dev@dpdk.org; Pattan, Reshma <reshma.pattan@intel.com>; Thomas > > > > Monjalon <thomas.monjalon@6wind.com> > > > > Subject: Re: [dpdk-dev] [PATCH v7 5/6] lib: added new library for > > > > latency stats > > > > > > > > On Mon, Jan 16, 2017 at 04:19:32PM +0000, Remy Horton wrote: > > > > > From: Reshma Pattan <reshma.pattan@intel.com> > > > > > > > > > > Add a library designed to calculate latency statistics and report > > > > > them to the application when queried. The library measures > > > > > minimum, average and maximum latencies, and jitter in nano > > > > > seconds. The current implementation supports global latency stats, > > > > > i.e. per application > > > > stats. > > > > > > > > > > Signed-off-by: Reshma Pattan <reshma.pattan@intel.com> > > > > > Signed-off-by: Remy Horton <remy.horton@intel.com> > > > > > --- > > > > > MAINTAINERS | 4 + > > > > > config/common_base | 5 + > > > > > doc/api/doxy-api-index.md | 1 + > > > > > doc/api/doxy-api.conf | 1 + > > > > > doc/guides/rel_notes/release_17_02.rst | 5 + > > > > > lib/Makefile | 1 + > > > > > lib/librte_latencystats/Makefile | 57 +++ > > > > > lib/librte_latencystats/rte_latencystats.c | 389 > > > > +++++++++++++++++++++ > > > > > lib/librte_latencystats/rte_latencystats.h | 146 ++++++++ > > > > > .../rte_latencystats_version.map | 10 + > > > > > lib/librte_mbuf/rte_mbuf.h | 3 + > > > > > > > > It is a value added feature for DPDK. But what is the plan for > > > > incorporating the mbuf change? I have 8 month old mbuf change for > > > > ARM for natural alignment. If we are accepting any mbuf change then > > > > we need to include outstanding mbuf changes to avoid future ABI > > breakage. > > > > > > > > http://dpdk.org/dev/patchwork/patch/12878/ > > > > > > > > > > Hi Jerin, > > > > Hi John, > > > > > > > > As far as I know the plan was to reach some sort of consensus on the > > > mbuf structure at the DPDK Userspace 2016, during and after Olivier's > > > presentation and then to make those changes during 17.02. > > > > > > However, I believe Olivier had other work commitments in this release > > > and wasn't able to work on the mbuf changes. > > > > > > The above mbuf change (and addition at the end of the struct) should > > > have gone into that mbuf rework, along with your changes. > > > > > > However, since the mbuf rework didn't happen we need to add the field > > > in this release. > > > > So we don't care the mbuf ABI breakage in the next release. This wasn't > > the message I got earlier for ARM's mbuf change. > > > > http://dpdk.org/dev/patchwork/patch/12878/ > > > Hi Jerin, > > We do care about ABI breakage but I was under the impression that the > timestamp change wasn't breaking the ABI since it was at the end of the > struct. I also ran the ABI validator against the change and it didn't show any > breakage. > > http://dpdk.org/doc/guides/contributing/versioning.html#running-the-abi-validator > > The rearm_data alignment patch, on the other hand, does break ABI. I think > that is the main difference between the two patches. > > If the timestamp change does break ABI then it should also wait until the mbuf > restructuring. I agree on ABI part. If understand it correctly, Oliver would like to group all the mbuf modification in one version and postponed the rearm_data change. Here is the email --------------------------------------------------------- Changing the mbuf topology is something that should happen as rarely as possible, so I think we should group all mbuf modifications in one version. Your issue (mbuf->rearm alignment), the removing of uneeded fields (port id, maybe nb_segs), and possibly other things should be addressed for next version (16.11). I'll send a deprecation notice before the 16.07 is out if there is no opposition. --------------------------------------------------------- > > > > ... > > > > There is nothing against you or this feature. The only part concerns me > > that some set of patches can always override any rule and include in the > > release (even as marking as EXPERIMENTAL) because of its important for > > some set of consumers. > > Another set has to wait in the queue because its not important for some > > people. > > For me, it is not a sign of vendor neutral open source project. > > To be fair I don't think we are trying to override any rule here. > > Also, we aren't the only vendor looking for a timestamp in the mbuf. > Mellanox also submitted a patch: > > http://dpdk.org/ml/archives/dev/2016-October/048809.html We don't have any issue in adding timestamp in mbuf either. The point, I was trying to make some changes like rearm_data only need for ARM architecture.In those cases, postponing the changes due to some other non direct dependency change is not good a specific architecture/vendor. > > However, it is also fair to acknowledge that the rearm_data alignment patch > shouldn't have had to wait so long. I can't really answer for that directly. > My feeling is that it was targeted for the mbuf rework but got forgotten > when that work slipped. Oliver, Could you please suggest how to proceed further? > > John > > ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [PATCH v7 5/6] lib: added new library for latency stats 2017-01-17 16:25 ` Jerin Jacob @ 2017-01-18 20:11 ` Olivier Matz 2017-01-24 15:24 ` Olivier MATZ 0 siblings, 1 reply; 115+ messages in thread From: Olivier Matz @ 2017-01-18 20:11 UTC (permalink / raw) To: Jerin Jacob Cc: Mcnamara, John, Horton, Remy, dev, Pattan, Reshma, Thomas Monjalon, Richardson, Bruce Hi guys, On Tue, 17 Jan 2017 21:55:16 +0530, Jerin Jacob > Oliver, > > Could you please suggest how to proceed further? > Sorry for the lack of response. I know people are waiting for me, but these days I have too many things to do at the same time, and it's difficult to find time. In few words (I'll provide more detailed answers to the thread by friday): I expected to post the mbuf rework patchset for this release, which includes the structure changes (Jerin's patch for arm access, timestamp, port, nb_segs, refcnt changes). But the patchset is clearly not ready yet, it needs a rebase, and it lacks test. Jerin, I know that you submitted your patch a long time ago, and I'm the only one to blame, please do not see any vendor preference in it. I'll check friday what's the effective state of the patchset in my workspace. If I can extract a minimal patch that only change the structure, I'll send it for discussion. But from what I remember, the mbuf structure rework depends on changing the way we access the refcnt, so it can be moved to the 2nd cache line. If that's not possible, I'll try propose some alternatives. Regards, Olivier ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [PATCH v7 5/6] lib: added new library for latency stats 2017-01-18 20:11 ` Olivier Matz @ 2017-01-24 15:24 ` Olivier MATZ 0 siblings, 0 replies; 115+ messages in thread From: Olivier MATZ @ 2017-01-24 15:24 UTC (permalink / raw) To: Olivier Matz Cc: Jerin Jacob, Mcnamara, John, Horton, Remy, dev, Pattan, Reshma, Thomas Monjalon, Richardson, Bruce On Wed, 18 Jan 2017 21:11:28 +0100, Olivier Matz <olivier.matz@6wind.com> wrote: > Hi guys, > > On Tue, 17 Jan 2017 21:55:16 +0530, Jerin Jacob > > Oliver, > > > > Could you please suggest how to proceed further? > > > > Sorry for the lack of response. I know people are waiting for > me, but these days I have too many things to do at the same time, and > it's difficult to find time. > > In few words (I'll provide more detailed answers to the thread by > friday): I expected to post the mbuf rework patchset for this release, > which includes the structure changes (Jerin's patch for arm access, > timestamp, port, nb_segs, refcnt changes). But the patchset is clearly > not ready yet, it needs a rebase, and it lacks test. > > Jerin, I know that you submitted your patch a long time ago, and I'm > the only one to blame, please do not see any vendor preference in it. > > I'll check friday what's the effective state of the patchset in my > workspace. If I can extract a minimal patch that only change the > structure, I'll send it for discussion. But from what I remember, the > mbuf structure rework depends on changing the way we access the > refcnt, so it can be moved to the 2nd cache line. > > If that's not possible, I'll try propose some alternatives. I just posted a mbuf RFC patchset [1]. I think it contains most things that were mentioned on the ML. As checked with Thomas, it's too late to have it included in 17.02. I'll tend to agree with John that having the timestamp in the mbuf for latency is not an ABI break, since it is added at the end of the structure. So I won't oppose to add this field in the mbuf structure for the release. The mbuf rearm patch was not forgotten, but it took clearly too long to be integrated. With the benefit of hindsight, it should have been pushed without waiting the mbuf rework. Again, apologies for that, I understand it's quite frustrating. Anyway, tests or comments on my RFC patchset are welcome, so we can integrate it at the beginning of the 17.05 cycle. Regards, Olivier [1] http://dpdk.org/ml/archives/dev/2017-January/056187.html ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [PATCH v7 5/6] lib: added new library for latency stats 2017-01-16 16:19 ` [dpdk-dev] [PATCH v7 5/6] lib: added new library for latency stats Remy Horton 2017-01-17 4:29 ` Jerin Jacob @ 2017-01-17 11:41 ` Van Haaren, Harry 1 sibling, 0 replies; 115+ messages in thread From: Van Haaren, Harry @ 2017-01-17 11:41 UTC (permalink / raw) To: Horton, Remy, dev; +Cc: Pattan, Reshma, Thomas Monjalon > -----Original Message----- > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Remy Horton > Sent: Monday, January 16, 2017 4:20 PM > To: dev@dpdk.org > Cc: Pattan, Reshma <reshma.pattan@intel.com>; Thomas Monjalon <thomas.monjalon@6wind.com> > Subject: [dpdk-dev] [PATCH v7 5/6] lib: added new library for latency stats > > From: Reshma Pattan <reshma.pattan@intel.com> > > Add a library designed to calculate latency statistics and report them > to the application when queried. The library measures minimum, average and > maximum latencies, and jitter in nano seconds. The current implementation > supports global latency stats, i.e. per application stats. > > Signed-off-by: Reshma Pattan <reshma.pattan@intel.com> > Signed-off-by: Remy Horton <remy.horton@intel.com> > --- This patch addresses a few changes - and should probably be split out a bit more than the v6 -> v7 changes done. In particular, the mbuf change should be its own commit to make it visible in the git log. Detailed comments inline. > diff --git a/MAINTAINERS b/MAINTAINERS > index 6cd9896..0a41fe5 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -714,3 +714,7 @@ F: examples/tep_termination/ > F: examples/vmdq/ > F: examples/vmdq_dcb/ > F: doc/guides/sample_app_ug/vmdq_dcb_forwarding.rst > + > +Latency Stats > +M: Reshma Pattan <reshma.pattan@intel.com> > +F: lib/librte_latencystats/ Wrong section? This should be added to the "other libraries" I think. > +++ b/lib/librte_latencystats/Makefile > @@ -0,0 +1,57 @@ > +# BSD LICENSE > +# > +# Copyright(c) 2016 Intel Corporation. All rights reserved. > +# All rights reserved. -2017 > +++ b/lib/librte_latencystats/rte_latencystats.c > @@ -0,0 +1,389 @@ > +/*- > + * BSD LICENSE > + * > + * Copyright(c) 2016 Intel Corporation. All rights reserved. > + * All rights reserved. -2017 > + > +/** Nano seconds per second */ > +#define NS_PER_SEC 1E9 > + > +/** Clock cycles per nano second */ > +#define CYCLES_PER_NS (rte_get_timer_hz() / NS_PER_SEC) Concidering this calls a function, it should probably be a static inline function instead of a #define, so it is obvious this cannot be used for static initialization. > + > +/* Macros for printing using RTE_LOG */ > +#define RTE_LOGTYPE_LATENCY_STATS RTE_LOGTYPE_USER1 > + > +static pthread_t latency_stats_thread; Concerned about the pthread - see below. > +static const char *MZ_RTE_LATENCY_STATS = "rte_latencystats"; > +static int latency_stats_index; > +static uint64_t samp_intvl; > +static uint64_t timer_tsc; > +static uint64_t prev_tsc; > + > +static struct rte_latency_stats { > + float min_latency; /**< Minimum latency in nano seconds */ > + float avg_latency; /**< Average latency in nano seconds */ > + float max_latency; /**< Maximum latency in nano seconds */ > + float jitter; /** Latency variation */ > +} *glob_stats; Style guide advises against this type of initialization IIRC; http://dpdk.org/doc/guides/contributing/coding_style.html#structure-declarations Its not very clear, but I do think a separate line makes the variable declaration on its own line more obvious: static struct rte_latency_stats *glob_stats; > + > +static struct rxtx_cbs { > + struct rte_eth_rxtx_callback *cb; > +} rx_cbs[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT], > + tx_cbs[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT]; Same as previous comment - this struct looks very confusing to me :) Please declare explicitly on own lines: static struct rxtx_cbs { struct rte_eth_rxtx_callback *cb; }; static struct rxtx_cbs rx_cbs[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT]; static struct rxtx_cbs tx_cbs[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT]; > + > +struct latency_stats_nameoff { > + char name[RTE_ETH_XSTATS_NAME_SIZE]; > + unsigned int offset; > +}; > + > +static const struct latency_stats_nameoff lat_stats_strings[] = { > + {"min_latency_ns", offsetof(struct rte_latency_stats, min_latency)}, > + {"avg_latency_ns", offsetof(struct rte_latency_stats, avg_latency)}, > + {"max_latency_ns", offsetof(struct rte_latency_stats, max_latency)}, > + {"jitter_ns", offsetof(struct rte_latency_stats, jitter)}, > +}; > + > +#define NUM_LATENCY_STATS (sizeof(lat_stats_strings) / \ > + sizeof(lat_stats_strings[0])) > + > +static __attribute__((noreturn)) void * > +report_latency_stats(__rte_unused void *arg) > +{ > + for (;;) { > + unsigned int i; > + float *stats_ptr = NULL; > + uint64_t values[NUM_LATENCY_STATS] = {0}; > + int ret; > + > + for (i = 0; i < NUM_LATENCY_STATS; i++) { > + stats_ptr = RTE_PTR_ADD(glob_stats, > + lat_stats_strings[i].offset); > + values[i] = (uint64_t)floor((*stats_ptr)/ > + CYCLES_PER_NS); > + } > + > + ret = rte_metrics_update_metrics(RTE_METRICS_GLOBAL, > + latency_stats_index, > + values, NUM_LATENCY_STATS); > + if (ret < 0) > + RTE_LOG(INFO, LATENCY_STATS, > + "Failed to push the stats\n"); > + } > +} This function is strange - the library creates a pthread and then calls this function internally? This does not look like a good design from my point-of-view. The Timer library may be of use for inspiration, it requires the application polls a function to handle expired timers: void rte_timer_manage(). > +static void > +rte_latencystats_fill_values(struct rte_metric_value *values) > +{ > + unsigned int i; > + float *stats_ptr = NULL; > + > + for (i = 0; i < NUM_LATENCY_STATS; i++) { > + stats_ptr = RTE_PTR_ADD(glob_stats, > + lat_stats_strings[i].offset); > + values[i].key = i; > + values[i].value = (uint64_t)floor((*stats_ptr)/ > + CYCLES_PER_NS); > + } > +} > + > +static uint16_t > +add_time_stamps(uint8_t pid __rte_unused, > + uint16_t qid __rte_unused, > + struct rte_mbuf **pkts, > + uint16_t nb_pkts, > + uint16_t max_pkts __rte_unused, > + void *user_cb __rte_unused) > +{ > + unsigned int i; > + uint64_t diff_tsc, now; > + > + /* > + * For every sample interval, > + * time stamp is marked on one received packet. > + */ > + now = rte_rdtsc(); > + for (i = 0; i < nb_pkts; i++) { > + diff_tsc = now - prev_tsc; > + timer_tsc += diff_tsc; > + if (timer_tsc >= samp_intvl) { > + /* > + * TBD: Mark the timestamp only > + * if not already marked by the > + * hardware or the PMD. > + */ > + pkts[i]->timestamp = now; > + timer_tsc = 0; > + } > + prev_tsc = now; > + now = rte_rdtsc(); > + } > + > + return nb_pkts; > +} > + > +static uint16_t > +calc_latency(uint8_t pid __rte_unused, > + uint16_t qid __rte_unused, > + struct rte_mbuf **pkts, > + uint16_t nb_pkts, > + void *_ __rte_unused) > +{ > + unsigned int i, cnt = 0; > + uint64_t now; > + float latency[nb_pkts]; > + static float prev_latency; > + /* > + * Alpha represents degree of weighting decrease in EWMA, > + * a constant smoothing factor between 0 and 1. The value > + * is used below for measuring average latency. > + */ > + const float alpha = 0.2; > + > + now = rte_rdtsc(); > + for (i = 0; i < nb_pkts; i++) { > + if (pkts[i]->timestamp) > + latency[cnt++] = now - pkts[i]->timestamp; > + } > + > + for (i = 0; i < cnt; i++) { > + /* > + * The jitter is calculated as statistical mean of interpacket > + * delay variation. The "jitter estimate" is computed by taking > + * the absolute values of the ipdv sequence and applying an > + * exponential filter with parameter 1/16 to generate the > + * estimate. i.e J=J+(|D(i-1,i)|-J)/16. Where J is jitter, > + * D(i-1,i) is difference in latency of two consecutive packets > + * i-1 and i. > + * Reference: Calculated as per RFC 5481, sec 4.1, > + * RFC 3393 sec 4.5, RFC 1889 sec. > + */ > + glob_stats->jitter += (abs(prev_latency - latency[i]) > + - glob_stats->jitter)/16; > + if (glob_stats->min_latency == 0) > + glob_stats->min_latency = latency[i]; > + else if (latency[i] < glob_stats->min_latency) > + glob_stats->min_latency = latency[i]; > + else if (latency[i] > glob_stats->max_latency) > + glob_stats->max_latency = latency[i]; > + /* > + * The average latency is measured using exponential moving > + * average, i.e. using EWMA > + * https://en.wikipedia.org/wiki/Moving_average > + */ > + glob_stats->avg_latency += > + alpha * (latency[i] - glob_stats->avg_latency); > + prev_latency = latency[i]; > + } > + > + return nb_pkts; > +} > + > +int > +rte_latencystats_init(uint64_t samp_intvl, > + rte_latency_stats_flow_type_fn user_cb) > +{ > + unsigned int i; > + uint8_t pid; > + uint16_t qid; > + struct rxtx_cbs *cbs = NULL; > + const uint8_t nb_ports = rte_eth_dev_count(); > + const char *ptr_strings[NUM_LATENCY_STATS] = {0}; > + const struct rte_memzone *mz = NULL; > + const unsigned int flags = 0; > + > + /** Allocate stats in shared memory fo muliti process support */ > + mz = rte_memzone_reserve(MZ_RTE_LATENCY_STATS, sizeof(*glob_stats), > + rte_socket_id(), flags); > + if (mz == NULL) { > + RTE_LOG(ERR, LATENCY_STATS, "Cannot reserve memory: %s:%d\n", > + __func__, __LINE__); > + return -ENOMEM; > + } There is no check for double-initialization of the library - although it is an application error to initialize twice, the library should handle it. > + > + glob_stats = mz->addr; > + samp_intvl *= CYCLES_PER_NS; > + > + /** Register latency stats with stats library */ > + for (i = 0; i < NUM_LATENCY_STATS; i++) > + ptr_strings[i] = lat_stats_strings[i].name; > + > + latency_stats_index = rte_metrics_reg_metrics(ptr_strings, > + NUM_LATENCY_STATS); > + if (latency_stats_index < 0) { > + RTE_LOG(DEBUG, LATENCY_STATS, > + "Failed to register latency stats names\n"); > + return -1; > + } > + > + /** Register Rx/Tx callbacks */ > + for (pid = 0; pid < nb_ports; pid++) { > + struct rte_eth_dev_info dev_info; > + rte_eth_dev_info_get(pid, &dev_info); > + for (qid = 0; qid < dev_info.nb_rx_queues; qid++) { > + cbs = &rx_cbs[pid][qid]; > + cbs->cb = rte_eth_add_first_rx_callback(pid, qid, > + add_time_stamps, user_cb); > + if (!cbs->cb) > + RTE_LOG(INFO, LATENCY_STATS, "Failed to " > + "register Rx callback for pid=%d, " > + "qid=%d\n", pid, qid); > + } > + for (qid = 0; qid < dev_info.nb_tx_queues; qid++) { > + cbs = &tx_cbs[pid][qid]; > + cbs->cb = rte_eth_add_tx_callback(pid, qid, > + calc_latency, user_cb); > + if (!cbs->cb) > + RTE_LOG(INFO, LATENCY_STATS, "Failed to " > + "register Tx callback for pid=%d, " > + "qid=%d\n", pid, qid); > + } > + } > + > + int ret = 0; > + char thread_name[RTE_MAX_THREAD_NAME_LEN]; > + > + /** Create the host thread to update latency stats to stats library */ > + ret = pthread_create(&latency_stats_thread, NULL, report_latency_stats, > + NULL); > + if (ret != 0) { > + RTE_LOG(ERR, LATENCY_STATS, > + "Failed to create the latency stats thread:%s, %s:%d\n", > + strerror(errno), __func__, __LINE__); > + return -1; > + } This pthread_create() raises some flags, spawning a thread "behind the applications back" isn't a good plan. We should require a thread poll the latency stats, not create a thread ourselves. See note above on using an application thread. > + /** Set thread_name for aid in debugging */ > + snprintf(thread_name, RTE_MAX_THREAD_NAME_LEN, "latency-stats-thread"); > + ret = rte_thread_setname(latency_stats_thread, thread_name); > + if (ret != 0) > + RTE_LOG(DEBUG, LATENCY_STATS, > + "Failed to set thread name for latency stats handling\n"); > + > + return 0; > +} > + > +int > +rte_latencystats_uninit(void) > +{ > + uint8_t pid; > + uint16_t qid; > + int ret = 0; > + struct rxtx_cbs *cbs = NULL; > + const uint8_t nb_ports = rte_eth_dev_count(); > + > + /** De register Rx/Tx callbacks */ > + for (pid = 0; pid < nb_ports; pid++) { > + struct rte_eth_dev_info dev_info; > + rte_eth_dev_info_get(pid, &dev_info); > + for (qid = 0; qid < dev_info.nb_rx_queues; qid++) { > + cbs = &rx_cbs[pid][qid]; > + ret = rte_eth_remove_rx_callback(pid, qid, cbs->cb); > + if (ret) > + RTE_LOG(INFO, LATENCY_STATS, "failed to " > + "remove Rx callback for pid=%d, " > + "qid=%d\n", pid, qid); > + } > + for (qid = 0; qid < dev_info.nb_tx_queues; qid++) { > + cbs = &tx_cbs[pid][qid]; > + ret = rte_eth_remove_tx_callback(pid, qid, cbs->cb); > + if (ret) > + RTE_LOG(INFO, LATENCY_STATS, "failed to " > + "remove Tx callback for pid=%d, " > + "qid=%d\n", pid, qid); > + } > + } > + > + /** Cancel the thread */ > + ret = pthread_cancel(latency_stats_thread); > + if (ret != 0) { > + RTE_LOG(ERR, LATENCY_STATS, > + "Failed to cancel latency stats update thread:" > + "%s,%s:%d\n", > + strerror(errno), __func__, __LINE__); > + return -1; > + } > + > + return 0; > +} > + > +int > +rte_latencystats_get_names(struct rte_metric_name *names, uint16_t size) > +{ > + unsigned int i; > + > + if (names == NULL || size < NUM_LATENCY_STATS) > + return NUM_LATENCY_STATS; > + > + for (i = 0; i < NUM_LATENCY_STATS; i++) > + snprintf(names[i].name, sizeof(names[i].name), > + "%s", lat_stats_strings[i].name); > + > + return NUM_LATENCY_STATS; > +} > + > +int > +rte_latencystats_get(struct rte_metric_value *values, uint16_t size) > +{ > + if (size < NUM_LATENCY_STATS || values == NULL) > + return NUM_LATENCY_STATS; > + > + if (rte_eal_process_type() == RTE_PROC_SECONDARY) { > + const struct rte_memzone *mz; > + mz = rte_memzone_lookup(MZ_RTE_LATENCY_STATS); > + if (mz == NULL) { > + RTE_LOG(ERR, LATENCY_STATS, > + "Latency stats memzone not found\n"); > + return -ENOMEM; > + } > + glob_stats = mz->addr; > + } > + > + /* Retrieve latency stats */ > + rte_latencystats_fill_values(values); > + > + return NUM_LATENCY_STATS; > +} > diff --git a/lib/librte_latencystats/rte_latencystats.h > b/lib/librte_latencystats/rte_latencystats.h > new file mode 100644 > index 0000000..405b878 > --- /dev/null > +++ b/lib/librte_latencystats/rte_latencystats.h > @@ -0,0 +1,146 @@ > +/*- > + * BSD LICENSE > + * > + * Copyright(c) 2016 Intel Corporation. All rights reserved. > + * All rights reserved. > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * > + * * Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * * Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in > + * the documentation and/or other materials provided with the > + * distribution. > + * * Neither the name of Intel Corporation nor the names of its > + * contributors may be used to endorse or promote products derived > + * from this software without specific prior written permission. > + * > + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS > + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT > + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR > + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT > + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, > + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT > + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, > + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY > + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT > + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE > + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. > + */ > + > +#ifndef _RTE_LATENCYSTATS_H_ > +#define _RTE_LATENCYSTATS_H_ > + > +/** > + * @file > + * RTE latency stats > + * > + * library to provide application and flow based latency stats. > + */ > + > +#include <rte_metrics.h> > + > +#ifdef __cplusplus > +extern "C" { > +#endif > + > +/** > + * Note: This function pointer is for future flow based latency stats > + * implementation. > + * > + * Function type used for identifting flow types of a Rx packet. > + * > + * The callback function is called on Rx for each packet. > + * This function is used for flow based latency calculations. > + * > + * @param pkt > + * Packet that has to be identified with its flow types. > + * @param user_param > + * The arbitrary user parameter passed in by the application when > + * the callback was originally configured. > + * @return > + * The flow_mask, representing the multiple flow types of a packet. > + */ > +typedef uint16_t (*rte_latency_stats_flow_type_fn)(struct rte_mbuf *pkt, > + void *user_param); > + > +/** > + * Registers Rx/Tx callbacks for each active port, queue. > + * > + * @param samp_intvl > + * Sampling time period in nano seconds, at which packet > + * should be marked with time stamp. > + * @param user_cb > + * Note: This param is for future flow based latency stats > + * implementation. > + * User callback to be called to get flow types of a packet. > + * Used for flow based latency calculation. > + * If the value is NULL, global stats will be calculated, > + * else flow based latency stats will be calculated. > + * For now just pass on the NULL value to this param. > + * @return > + * -1 : On error > + * -ENOMEM: On error > + * 0 : On success > + */ > +int rte_latencystats_init(uint64_t samp_intvl, > + rte_latency_stats_flow_type_fn user_cb); > + > +/** > + * Removes registered Rx/Tx callbacks for each active port, queue. > + * > + * @return > + * -1: On error > + * 0: On success > + */ > +int rte_latencystats_uninit(void); > + > +/** > + * Retrieve names of latency statistics > + * > + * @param names > + * Block of memory to insert names into. Must be at least size in capacity. > + * If set to NULL, function returns required capacity. > + * @param size > + * Capacity of latency stats names (number of names). > + * @return > + * - positive value lower or equal to size: success. The return value > + * is the number of entries filled in the stats table. > + * - positive value higher than size: error, the given statistics table > + * is too small. The return value corresponds to the size that should > + * be given to succeed. The entries in the table are not valid and > + * shall not be used by the caller. > + */ > +int rte_latencystats_get_names(struct rte_metric_name *names, > + uint16_t size); > + > +/** > + * Retrieve latency statistics. > + * > + * @param values > + * A pointer to a table of structure of type *rte_metric_value* > + * to be filled with latency statistics ids and values. > + * This parameter can be set to NULL if size is 0. > + * @param size > + * The size of the stats table, which should be large enough to store > + * all the latency stats. > + * @return > + * - positive value lower or equal to size: success. The return value > + * is the number of entries filled in the stats table. > + * - positive value higher than size: error, the given statistics table > + * is too small. The return value corresponds to the size that should > + * be given to succeed. The entries in the table are not valid and > + * shall not be used by the caller. > + * -ENOMEM: On failure. > + */ > +int rte_latencystats_get(struct rte_metric_value *values, > + uint16_t size); > + > +#ifdef __cplusplus > +} > +#endif > + > +#endif /* _RTE_LATENCYSTATS_H_ */ > diff --git a/lib/librte_latencystats/rte_latencystats_version.map > b/lib/librte_latencystats/rte_latencystats_version.map > new file mode 100644 > index 0000000..502018e > --- /dev/null > +++ b/lib/librte_latencystats/rte_latencystats_version.map > @@ -0,0 +1,10 @@ > +DPDK_17.02 { > + global: > + > + rte_latencystats_get; > + rte_latencystats_get_names; > + rte_latencystats_init; > + rte_latencystats_uninit; > + > + local: *; > +}; > diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h > index bfce9f4..c35ba0a 100644 > --- a/lib/librte_mbuf/rte_mbuf.h > +++ b/lib/librte_mbuf/rte_mbuf.h > @@ -512,6 +512,9 @@ struct rte_mbuf { > > /** Timesync flags for use with IEEE1588. */ > uint16_t timesync; > + > + /** Timestamp for measuring latency. */ > + uint64_t timestamp; > } __rte_cache_aligned; > This change needs its own patch, so it can be reviewed independently and the position in the struct for timestamp can be analysed easily. > /** > diff --git a/mk/rte.app.mk b/mk/rte.app.mk > index 6aac5ac..1d36fad 100644 > --- a/mk/rte.app.mk > +++ b/mk/rte.app.mk > @@ -100,7 +100,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE) += -lrte_cmdline > _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE) += -lrte_cfgfile > _LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS) += -lrte_metrics > _LDLIBS-$(CONFIG_RTE_LIBRTE_BITRATE) += -lrte_bitratestats > - > +_LDLIBS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += -lrte_latencystats > > _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += -lrte_pmd_bond > _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += -lrte_pmd_xenvirt -lxenstore > -- > 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v7 6/6] app/test-pmd: add latency statistics calculation 2017-01-16 16:19 ` [dpdk-dev] [PATCH v7 0/6] " Remy Horton ` (4 preceding siblings ...) 2017-01-16 16:19 ` [dpdk-dev] [PATCH v7 5/6] lib: added new library for latency stats Remy Horton @ 2017-01-16 16:19 ` Remy Horton 2017-01-17 11:45 ` Van Haaren, Harry 2017-01-17 23:24 ` [dpdk-dev] [PATCH v8 0/7] Expanded statistics reporting Remy Horton 6 siblings, 1 reply; 115+ messages in thread From: Remy Horton @ 2017-01-16 16:19 UTC (permalink / raw) To: dev; +Cc: Reshma Pattan, Thomas Monjalon From: Reshma Pattan <reshma.pattan@intel.com> Modify testpmd code to initialize/uninitialize latency statistics calulation. Signed-off-by: Reshma Pattan <reshma.pattan@intel.com> Signed-off-by: Remy Horton <remy.horton@intel.com> --- app/test-pmd/testpmd.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c index a0b7430..2874ce4 100644 --- a/app/test-pmd/testpmd.c +++ b/app/test-pmd/testpmd.c @@ -83,6 +83,10 @@ #ifdef RTE_LIBRTE_BITRATE #include <rte_bitrate.h> #endif +#include <rte_metrics.h> +#ifdef RTE_LIBRTE_LATENCY_STATS +#include <rte_latencystats.h> +#endif #include "testpmd.h" @@ -2108,6 +2112,9 @@ signal_handler(int signum) /* uninitialize packet capture framework */ rte_pdump_uninit(); #endif +#ifdef RTE_LIBRTE_LATENCY_STATS + rte_latencystats_uninit(); +#endif force_quit(); /* exit with the expected status */ signal(signum, SIG_DFL); @@ -2165,6 +2172,9 @@ main(int argc, char** argv) /* set all ports to promiscuous mode by default */ FOREACH_PORT(port_id, ports) rte_eth_promiscuous_enable(port_id); +#ifdef RTE_LIBRTE_LATENCY_STATS + rte_latencystats_init(1, NULL); +#endif /* Setup bitrate stats */ #ifdef RTE_LIBRTE_BITRATE -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [PATCH v7 6/6] app/test-pmd: add latency statistics calculation 2017-01-16 16:19 ` [dpdk-dev] [PATCH v7 6/6] app/test-pmd: add latency statistics calculation Remy Horton @ 2017-01-17 11:45 ` Van Haaren, Harry 0 siblings, 0 replies; 115+ messages in thread From: Van Haaren, Harry @ 2017-01-17 11:45 UTC (permalink / raw) To: Horton, Remy, dev; +Cc: Pattan, Reshma, Thomas Monjalon > -----Original Message----- > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Remy Horton > Sent: Monday, January 16, 2017 4:20 PM > To: dev@dpdk.org > Cc: Pattan, Reshma <reshma.pattan@intel.com>; Thomas Monjalon <thomas.monjalon@6wind.com> > Subject: [dpdk-dev] [PATCH v7 6/6] app/test-pmd: add latency statistics calculation > > From: Reshma Pattan <reshma.pattan@intel.com> > > Modify testpmd code to initialize/uninitialize latency statistics > calulation. > > Signed-off-by: Reshma Pattan <reshma.pattan@intel.com> > Signed-off-by: Remy Horton <remy.horton@intel.com> Comment inline. > --- > app/test-pmd/testpmd.c | 10 ++++++++++ > 1 file changed, 10 insertions(+) > > diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c > index a0b7430..2874ce4 100644 > --- a/app/test-pmd/testpmd.c > +++ b/app/test-pmd/testpmd.c > @@ -83,6 +83,10 @@ > #ifdef RTE_LIBRTE_BITRATE > #include <rte_bitrate.h> > #endif > +#include <rte_metrics.h> > +#ifdef RTE_LIBRTE_LATENCY_STATS > +#include <rte_latencystats.h> > +#endif > > #include "testpmd.h" > > @@ -2108,6 +2112,9 @@ signal_handler(int signum) > /* uninitialize packet capture framework */ > rte_pdump_uninit(); > #endif > +#ifdef RTE_LIBRTE_LATENCY_STATS > + rte_latencystats_uninit(); > +#endif > force_quit(); > /* exit with the expected status */ > signal(signum, SIG_DFL); > @@ -2165,6 +2172,9 @@ main(int argc, char** argv) > /* set all ports to promiscuous mode by default */ > FOREACH_PORT(port_id, ports) > rte_eth_promiscuous_enable(port_id); > +#ifdef RTE_LIBRTE_LATENCY_STATS > + rte_latencystats_init(1, NULL); > +#endif The 1 here represents reporting time in ns correct? 1 ns seems a very short amount of time. Perhaps clarify (here or in the header) what exactly this number does, or set it to 0 for "as fast as possible"? > > /* Setup bitrate stats */ > #ifdef RTE_LIBRTE_BITRATE > -- > 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v8 0/7] Expanded statistics reporting 2017-01-16 16:19 ` [dpdk-dev] [PATCH v7 0/6] " Remy Horton ` (5 preceding siblings ...) 2017-01-16 16:19 ` [dpdk-dev] [PATCH v7 6/6] app/test-pmd: add latency statistics calculation Remy Horton @ 2017-01-17 23:24 ` Remy Horton 2017-01-17 23:24 ` [dpdk-dev] [PATCH v8 1/7] lib: add information metrics library Remy Horton ` (7 more replies) 6 siblings, 8 replies; 115+ messages in thread From: Remy Horton @ 2017-01-17 23:24 UTC (permalink / raw) To: dev; +Cc: Thomas Monjalon This patchset extends statistics reporting to include peak and average data-rate metrics. It comes in two parts: a statistics reporting library, and a bitrate calculation library that uses it. This structure is intended to seperate statistic reporting from ethdev and allow more flexible metric registration. -- v8 changes: * Release notes correction * Updated copyright years * rte_metric_init() takes socket id & must be explicitly called * rte_metrics_reg_metric renamed to rte_metrics_reg_name() * rte_metrics_update_metric() renamed to rte_metrics_update_value() * Doxygen updates * Changed malloc()/free() to rte_malloc()/rte_free() * Removed redundant memset() * rte_stats_bitrates_s renamed to rte_stats_bitrates_s * Split mbuf change to own patch for visibility * CYCLES_PER_NS now a static inline function * latency: "hidden" pthread creation now has polling API instead. * Struct declarations and variable definitions cleaned up * Double initialization of the latency library now returns -EEXIST * MAINTAINERS entry for layenctstats in correct section v7 changes: * RTE_METRICS_NONPORT renamed to RTE_METRICS_GLOBAL * Multiple changes to rte_metrics.h doxygen documentation * Split apart latency patch into lib, test-pmd, & proc_info parts * Reordered patches by functionality * Insufficent capacity return value changed from -ERANGE to actual size * Cache alignment in bitrate library * Tightened up const usage to avoid STATIC_CONST_CHAR_ARRAY warning * Reshma reinstated as author for (now split) latency patch * Rebase to master v6 changes: * Metrics display now has "Non port specific" rather than "port -1" * Fixed sign issue in EWMA delta calculation * Rebased to master v5 changes: * Updated Shared Library Versions in release notes * Merged in Reshma's latencystats library v4 changes: * References to 16.11 changed to 17.02 * Fetching of non-port values was broken * Added sanity checks to value fetching * rte_stat_value renamed to rte_metric_value * Corrected doxygen descriptions * Added MAINTAINERS entries * Added #ifdef directives to bitrate code in test-pmd v3 changes: * Marked rte_stats_bitrate_s as internal * Minor integer roundoff correction * Coding style corrections * Removed spurious object allocation * Changes to rte_metrics.[ch] moved from Patch 2/3 to 1/3. * Reintroduced non-port values (RTE_METRICS_NONPORT) * Added spinlocks to metric library * Removed spurious test registration/update * Added release notes entries v2 changes: * Uses a new metrics library rather than being part of ethdev Harry van Haaren (3): mbuf: add a timestamp to the mbuf for latencystats lib: added new library for latency stats app/test-pmd: add latency statistics calculation Remy Horton (3): lib: add information metrics library lib: add bitrate statistics library app/test-pmd: add bitrate statistics calculation Reshma Pattan (1): app/proc_info: add metrics displaying MAINTAINERS | 12 + app/proc_info/main.c | 74 ++++- app/test-pmd/parameters.c | 20 +- app/test-pmd/testpmd.c | 75 ++++- app/test-pmd/testpmd.h | 6 +- config/common_base | 15 + doc/api/doxy-api-index.md | 3 + doc/api/doxy-api.conf | 3 + doc/guides/rel_notes/release_17_02.rst | 18 + lib/Makefile | 3 + lib/librte_bitratestats/Makefile | 53 +++ lib/librte_bitratestats/rte_bitrate.c | 132 ++++++++ lib/librte_bitratestats/rte_bitrate.h | 80 +++++ .../rte_bitratestats_version.map | 9 + lib/librte_latencystats/Makefile | 56 ++++ lib/librte_latencystats/rte_latencystats.c | 366 +++++++++++++++++++++ lib/librte_latencystats/rte_latencystats.h | 154 +++++++++ .../rte_latencystats_version.map | 10 + lib/librte_mbuf/rte_mbuf.h | 3 + lib/librte_metrics/Makefile | 51 +++ lib/librte_metrics/rte_metrics.c | 308 +++++++++++++++++ lib/librte_metrics/rte_metrics.h | 231 +++++++++++++ lib/librte_metrics/rte_metrics_version.map | 13 + mk/rte.app.mk | 3 + 24 files changed, 1694 insertions(+), 4 deletions(-) create mode 100644 lib/librte_bitratestats/Makefile create mode 100644 lib/librte_bitratestats/rte_bitrate.c create mode 100644 lib/librte_bitratestats/rte_bitrate.h create mode 100644 lib/librte_bitratestats/rte_bitratestats_version.map create mode 100644 lib/librte_latencystats/Makefile create mode 100644 lib/librte_latencystats/rte_latencystats.c create mode 100644 lib/librte_latencystats/rte_latencystats.h create mode 100644 lib/librte_latencystats/rte_latencystats_version.map create mode 100644 lib/librte_metrics/Makefile create mode 100644 lib/librte_metrics/rte_metrics.c create mode 100644 lib/librte_metrics/rte_metrics.h create mode 100644 lib/librte_metrics/rte_metrics_version.map -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v8 1/7] lib: add information metrics library 2017-01-17 23:24 ` [dpdk-dev] [PATCH v8 0/7] Expanded statistics reporting Remy Horton @ 2017-01-17 23:24 ` Remy Horton 2017-01-17 23:24 ` [dpdk-dev] [PATCH v8 2/7] app/proc_info: add metrics displaying Remy Horton ` (6 subsequent siblings) 7 siblings, 0 replies; 115+ messages in thread From: Remy Horton @ 2017-01-17 23:24 UTC (permalink / raw) To: dev; +Cc: Thomas Monjalon This patch adds a new information metric library that allows other modules to register named metrics and update their values. It is intended to be independent of ethdev, rather than mixing ethdev and non-ethdev information in xstats. Signed-off-by: Remy Horton <remy.horton@intel.com> --- MAINTAINERS | 4 + config/common_base | 5 + doc/api/doxy-api-index.md | 1 + doc/api/doxy-api.conf | 1 + doc/guides/rel_notes/release_17_02.rst | 8 + lib/Makefile | 1 + lib/librte_metrics/Makefile | 51 +++++ lib/librte_metrics/rte_metrics.c | 308 +++++++++++++++++++++++++++++ lib/librte_metrics/rte_metrics.h | 231 ++++++++++++++++++++++ lib/librte_metrics/rte_metrics_version.map | 13 ++ mk/rte.app.mk | 2 + 11 files changed, 625 insertions(+) create mode 100644 lib/librte_metrics/Makefile create mode 100644 lib/librte_metrics/rte_metrics.c create mode 100644 lib/librte_metrics/rte_metrics.h create mode 100644 lib/librte_metrics/rte_metrics_version.map diff --git a/MAINTAINERS b/MAINTAINERS index 9645c9b..95836a2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -596,6 +596,10 @@ F: lib/librte_jobstats/ F: examples/l2fwd-jobstats/ F: doc/guides/sample_app_ug/l2_forward_job_stats.rst +Metrics +M: Remy Horton <remy.horton@intel.com> +F: lib/librte_metrics/ + Test Applications ----------------- diff --git a/config/common_base b/config/common_base index 8e9dcfa..0eb3866 100644 --- a/config/common_base +++ b/config/common_base @@ -593,3 +593,8 @@ CONFIG_RTE_APP_TEST_RESOURCE_TAR=n CONFIG_RTE_TEST_PMD=y CONFIG_RTE_TEST_PMD_RECORD_CORE_CYCLES=n CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n + +# +# Compile the device metrics library +# +CONFIG_RTE_LIBRTE_METRICS=y diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md index 72d59b2..94f0f69 100644 --- a/doc/api/doxy-api-index.md +++ b/doc/api/doxy-api-index.md @@ -150,4 +150,5 @@ There are many libraries, so their headers may be grouped by topics: [common] (@ref rte_common.h), [ABI compat] (@ref rte_compat.h), [keepalive] (@ref rte_keepalive.h), + [Device Metrics] (@ref rte_metrics.h), [version] (@ref rte_version.h) diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf index b340fcf..194b670 100644 --- a/doc/api/doxy-api.conf +++ b/doc/api/doxy-api.conf @@ -50,6 +50,7 @@ INPUT = doc/api/doxy-api-index.md \ lib/librte_mbuf \ lib/librte_mempool \ lib/librte_meter \ + lib/librte_metrics \ lib/librte_net \ lib/librte_pdump \ lib/librte_pipeline \ diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst index d445d64..4fca29b 100644 --- a/doc/guides/rel_notes/release_17_02.rst +++ b/doc/guides/rel_notes/release_17_02.rst @@ -34,6 +34,12 @@ New Features Refer to the previous release notes for examples. + * **Added information metric library.** + + A library that allows information metrics to be added and update. It is + intended to provide a reporting mechanism that is independent of the + ethdev library. + This section is a comment. do not overwrite or remove it. Also, make sure to start the actual text at the margin. ========================================================= @@ -161,6 +167,7 @@ The libraries prepended with a plus sign were incremented in this version. .. code-block:: diff librte_acl.so.2 + + librte_bitratestats.so.1 librte_cfgfile.so.2 librte_cmdline.so.2 librte_cryptodev.so.2 @@ -176,6 +183,7 @@ The libraries prepended with a plus sign were incremented in this version. librte_mbuf.so.2 librte_mempool.so.2 librte_meter.so.1 + + librte_metrics.so.1 librte_net.so.1 librte_pdump.so.1 librte_pipeline.so.3 diff --git a/lib/Makefile b/lib/Makefile index 990f23a..5d85dcf 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -58,6 +58,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_TABLE) += librte_table DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += librte_pipeline DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump +DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni diff --git a/lib/librte_metrics/Makefile b/lib/librte_metrics/Makefile new file mode 100644 index 0000000..8d6e23a --- /dev/null +++ b/lib/librte_metrics/Makefile @@ -0,0 +1,51 @@ +# BSD LICENSE +# +# Copyright(c) 2016 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +include $(RTE_SDK)/mk/rte.vars.mk + +# library name +LIB = librte_metrics.a + +CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) + +EXPORT_MAP := rte_metrics_version.map + +LIBABIVER := 1 + +# all source are stored in SRCS-y +SRCS-$(CONFIG_RTE_LIBRTE_METRICS) := rte_metrics.c + +# Install header file +SYMLINK-$(CONFIG_RTE_LIBRTE_METRICS)-include += rte_metrics.h + +DEPDIRS-$(CONFIG_RTE_LIBRTE_METRICS) += lib/librte_eal + +include $(RTE_SDK)/mk/rte.lib.mk diff --git a/lib/librte_metrics/rte_metrics.c b/lib/librte_metrics/rte_metrics.c new file mode 100644 index 0000000..5a67c85 --- /dev/null +++ b/lib/librte_metrics/rte_metrics.c @@ -0,0 +1,308 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016-2017 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <string.h> +#include <sys/queue.h> + +#include <rte_common.h> +#include <rte_malloc.h> +#include <rte_metrics.h> +#include <rte_lcore.h> +#include <rte_memzone.h> +#include <rte_spinlock.h> + +#define RTE_METRICS_MAX_METRICS 256 +#define RTE_METRICS_MEMZONE_NAME "RTE_METRICS" + +/** + * Internal stats metadata and value entry. + * + * @internal + * @param name + * Name of metric + * @param value + * Current value for metric + * @param idx_next_set + * Index of next root element (zero for none) + * @param idx_next_metric + * Index of next metric in set (zero for none) + * + * Only the root of each set needs idx_next_set but since it has to be + * assumed that number of sets could equal total number of metrics, + * having a separate set metadata table doesn't save any memory. + */ +struct rte_metrics_meta_s { + char name[RTE_METRICS_MAX_NAME_LEN]; + uint64_t value[RTE_MAX_ETHPORTS]; + uint64_t nonport_value; + uint16_t idx_next_set; + uint16_t idx_next_stat; +}; + +/** + * Internal stats info structure. + * + * @internal + * @param idx_last_set + * Index of last metadata entry with valid data. This value is + * not valid if cnt_stats is zero. + * @param cnt_stats + * Number of metrics. + * @param metadata + * Stat data memory block. + * + * Offsets into metadata are used instead of pointers because ASLR + * means that having the same physical addresses in different + * processes is not guaranteed. + */ +struct rte_metrics_data_s { + uint16_t idx_last_set; + uint16_t cnt_stats; + struct rte_metrics_meta_s metadata[RTE_METRICS_MAX_METRICS]; + rte_spinlock_t lock; +}; + +void +rte_metrics_init(int socket_id) +{ + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + + if (rte_eal_process_type() != RTE_PROC_PRIMARY) + return; + + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); + if (memzone != NULL) + return; + memzone = rte_memzone_reserve(RTE_METRICS_MEMZONE_NAME, + sizeof(struct rte_metrics_data_s), socket_id, 0); + if (memzone == NULL) + rte_exit(EXIT_FAILURE, "Unable to allocate stats memzone\n"); + stats = memzone->addr; + memset(stats, 0, sizeof(struct rte_metrics_data_s)); + rte_spinlock_init(&stats->lock); +} + +int +rte_metrics_reg_name(const char *name) +{ + const char * const list_names[] = {name}; + + return rte_metrics_reg_names(list_names, 1); +} + +int +rte_metrics_reg_names(const char * const *names, uint16_t cnt_names) +{ + struct rte_metrics_meta_s *entry; + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + uint16_t idx_name; + uint16_t idx_base; + + /* Some sanity checks */ + if (cnt_names < 1 || names == NULL) + return -EINVAL; + + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); + if (memzone == NULL) + return -EIO; + stats = memzone->addr; + + if (stats->cnt_stats + cnt_names >= RTE_METRICS_MAX_METRICS) + return -ENOMEM; + + rte_spinlock_lock(&stats->lock); + + /* Overwritten later if this is actually first set.. */ + stats->metadata[stats->idx_last_set].idx_next_set = stats->cnt_stats; + + stats->idx_last_set = idx_base = stats->cnt_stats; + + for (idx_name = 0; idx_name < cnt_names; idx_name++) { + entry = &stats->metadata[idx_name + stats->cnt_stats]; + strncpy(entry->name, names[idx_name], + RTE_METRICS_MAX_NAME_LEN); + memset(entry->value, 0, sizeof(entry->value)); + entry->idx_next_stat = idx_name + stats->cnt_stats + 1; + } + entry->idx_next_stat = 0; + entry->idx_next_set = 0; + stats->cnt_stats += cnt_names; + + rte_spinlock_unlock(&stats->lock); + + return idx_base; +} + +int +rte_metrics_update_value(int port_id, uint16_t key, const uint64_t value) +{ + return rte_metrics_update_values(port_id, key, &value, 1); +} + +int +rte_metrics_update_values(int port_id, + uint16_t key, + const uint64_t *values, + uint32_t count) +{ + struct rte_metrics_meta_s *entry; + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + uint16_t idx_metric; + uint16_t idx_value; + uint16_t cnt_setsize; + + if (port_id != RTE_METRICS_GLOBAL && + (port_id < 0 || port_id > RTE_MAX_ETHPORTS)) + return -EINVAL; + + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); + if (memzone == NULL) + return -EIO; + stats = memzone->addr; + + rte_spinlock_lock(&stats->lock); + idx_metric = key; + cnt_setsize = 1; + while (idx_metric < stats->cnt_stats) { + entry = &stats->metadata[idx_metric]; + if (entry->idx_next_stat == 0) + break; + cnt_setsize++; + idx_metric++; + } + /* Check update does not cross set border */ + if (count > cnt_setsize) { + rte_spinlock_unlock(&stats->lock); + return -ERANGE; + } + + if (port_id == RTE_METRICS_GLOBAL) + for (idx_value = 0; idx_value < count; idx_value++) { + idx_metric = key + idx_value; + stats->metadata[idx_metric].nonport_value = + values[idx_value]; + } + else + for (idx_value = 0; idx_value < count; idx_value++) { + idx_metric = key + idx_value; + stats->metadata[idx_metric].value[port_id] = + values[idx_value]; + } + rte_spinlock_unlock(&stats->lock); + return 0; +} + +int +rte_metrics_get_names(struct rte_metric_name *names, + uint16_t capacity) +{ + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + uint16_t idx_name; + int return_value; + + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); + /* If not allocated, fail silently */ + if (memzone == NULL) + return 0; + + stats = memzone->addr; + rte_spinlock_lock(&stats->lock); + if (names != NULL) { + if (capacity < stats->cnt_stats) { + return_value = stats->cnt_stats; + rte_spinlock_unlock(&stats->lock); + return return_value; + } + for (idx_name = 0; idx_name < stats->cnt_stats; idx_name++) + strncpy(names[idx_name].name, + stats->metadata[idx_name].name, + RTE_METRICS_MAX_NAME_LEN); + } + return_value = stats->cnt_stats; + rte_spinlock_unlock(&stats->lock); + return return_value; +} + +int +rte_metrics_get_values(int port_id, + struct rte_metric_value *values, + uint16_t capacity) +{ + struct rte_metrics_meta_s *entry; + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + uint16_t idx_name; + int return_value; + + if (port_id != RTE_METRICS_GLOBAL && + (port_id < 0 || port_id > RTE_MAX_ETHPORTS)) + return -EINVAL; + + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); + /* If not allocated, fail silently */ + if (memzone == NULL) + return 0; + stats = memzone->addr; + rte_spinlock_lock(&stats->lock); + + if (values != NULL) { + if (capacity < stats->cnt_stats) { + return_value = stats->cnt_stats; + rte_spinlock_unlock(&stats->lock); + return return_value; + } + if (port_id == RTE_METRICS_GLOBAL) + for (idx_name = 0; + idx_name < stats->cnt_stats; + idx_name++) { + entry = &stats->metadata[idx_name]; + values[idx_name].key = idx_name; + values[idx_name].value = entry->nonport_value; + } + else + for (idx_name = 0; + idx_name < stats->cnt_stats; + idx_name++) { + entry = &stats->metadata[idx_name]; + values[idx_name].key = idx_name; + values[idx_name].value = entry->value[port_id]; + } + } + return_value = stats->cnt_stats; + rte_spinlock_unlock(&stats->lock); + return return_value; +} diff --git a/lib/librte_metrics/rte_metrics.h b/lib/librte_metrics/rte_metrics.h new file mode 100644 index 0000000..871a8f9 --- /dev/null +++ b/lib/librte_metrics/rte_metrics.h @@ -0,0 +1,231 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016-2017 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * + * RTE Metrics module + * + * Metric information is populated using a push model, where the + * information provider calls an update function on the relevant + * metrics. Currently only bulk querying of metrics is supported. + */ + +#ifndef _RTE_METRICS_H_ +#define _RTE_METRICS_H_ + +/** Maximum length of metric name (including null-terminator) */ +#define RTE_METRICS_MAX_NAME_LEN 64 + +/** + * Global (rather than port-specific) metric. + * + * When used instead of port number by rte_metrics_update_metric() + * or rte_metrics_update_metric(), the global metrics, which are + * not associated with any specific port, are updated. + */ +#define RTE_METRICS_GLOBAL -1 + + +/** + * A name-key lookup for metrics. + * + * An array of this structure is returned by rte_metrics_get_names(). + * The struct rte_eth_stats references these names via their array index. + */ +struct rte_metric_name { + /** String describing metric */ + char name[RTE_METRICS_MAX_NAME_LEN]; +}; + + +/** + * Metric value structure. + * + * This structure is used by rte_metrics_get_values() to return metrics, + * which are statistics that are not generated by PMDs. It maps a name key, + * which corresponds to an index in the array returned by + * rte_metrics_get_names(). + */ +struct rte_metric_value { + /** Numeric identifier of metric. */ + uint16_t key; + /** Value for metric */ + uint64_t value; +}; + + +/** + * Initializes metric module. This function must be called from + * a primary process before metrics are used. + * + * @param socket_id + * Socket to use for shared memory allocation. + */ +void rte_metrics_init(int socket_id); + +/** + * Register a metric, making it available as a reporting parameter. + * + * Registering a metric is the way third-parties declare a parameter + * that they wish to be reported. Once registered, the associated + * numeric key can be obtained via rte_metrics_get_names(), which + * is required for updating said metric's value. + * + * @param name + * Metric name + * + * @return + * - Zero or positive: Success (index key of new metric) + * - \b -EIO: Error, unable to access metrics shared memory + * (rte_metrics_init() not called) + * - \b -EINVAL: Error, invalid parameters + * - \b -ENOMEM: Error, maximum metrics reached + */ +int rte_metrics_reg_name(const char *name); + +/** + * Register a set of metrics. + * + * This is a bulk version of rte_metrics_reg_metrics() and aside from + * handling multiple keys at once is functionally identical. + * + * @param names + * List of metric names + * + * @param cnt_names + * Number of metrics in set + * + * @return + * - Zero or positive: Success (index key of start of set) + * - \b -EIO: Error, unable to access metrics shared memory + * (rte_metrics_init() not called) + * - \b -EINVAL: Error, invalid parameters + * - \b -ENOMEM: Error, maximum metrics reached + */ +int rte_metrics_reg_names(const char * const *names, uint16_t cnt_names); + +/** + * Get metric name-key lookup table. + * + * @param names + * A struct rte_metric_name array of at least *capacity* in size to + * receive key names. If this is NULL, function returns the required + * number of elements for this array. + * + * @param capacity + * Size (number of elements) of struct rte_metric_name array. + * Disregarded if names is NULL. + * + * @return + * - Positive value above capacity: error, *names* is too small. + * Return value is required size. + * - Positive value equal or less than capacity: Success. Return + * value is number of elements filled in. + * - Negative value: error. + */ +int rte_metrics_get_names( + struct rte_metric_name *names, + uint16_t capacity); + +/** + * Get metric value table. + * + * @param port_id + * Port id to query + * + * @param values + * A struct rte_metric_value array of at least *capacity* in size to + * receive metric ids and values. If this is NULL, function returns + * the required number of elements for this array. + * + * @param capacity + * Size (number of elements) of struct rte_metric_value array. + * Disregarded if names is NULL. + * + * @return + * - Positive value above capacity: error, *values* is too small. + * Return value is required size. + * - Positive value equal or less than capacity: Success. Return + * value is number of elements filled in. + * - Negative value: error. + */ +int rte_metrics_get_values( + int port_id, + struct rte_metric_value *values, + uint16_t capacity); + +/** + * Updates a metric + * + * @param port_id + * Port to update metrics for + * @param key + * Id of metric to update + * @param value + * New value + * + * @return + * - -EIO if unable to access shared metrics memory + * - Zero on success + */ +int rte_metrics_update_value( + int port_id, + uint16_t key, + const uint64_t value); + +/** + * Updates a metric set. Note that it is an error to try to + * update across a set boundary. + * + * @param port_id + * Port to update metrics for + * @param key + * Base id of metrics set to update + * @param values + * Set of new values + * @param count + * Number of new values + * + * @return + * - -ERANGE if count exceeds metric set size + * - -EIO if upable to access shared metrics memory + * - Zero on success + */ +int rte_metrics_update_values( + int port_id, + uint16_t key, + const uint64_t *values, + uint32_t count); + +#endif diff --git a/lib/librte_metrics/rte_metrics_version.map b/lib/librte_metrics/rte_metrics_version.map new file mode 100644 index 0000000..f904814 --- /dev/null +++ b/lib/librte_metrics/rte_metrics_version.map @@ -0,0 +1,13 @@ +DPDK_17.02 { + global: + + rte_metrics_get_names; + rte_metrics_get_values; + rte_metrics_init; + rte_metrics_reg_metric; + rte_metrics_reg_metrics; + rte_metrics_update_metric; + rte_metrics_update_metrics; + + local: *; +}; diff --git a/mk/rte.app.mk b/mk/rte.app.mk index f75f0e2..40fcf33 100644 --- a/mk/rte.app.mk +++ b/mk/rte.app.mk @@ -98,6 +98,8 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_RING) += -lrte_ring _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL) += -lrte_eal _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE) += -lrte_cmdline _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE) += -lrte_cfgfile +_LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS) += -lrte_metrics + _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += -lrte_pmd_bond _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += -lrte_pmd_xenvirt -lxenstore -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v8 2/7] app/proc_info: add metrics displaying 2017-01-17 23:24 ` [dpdk-dev] [PATCH v8 0/7] Expanded statistics reporting Remy Horton 2017-01-17 23:24 ` [dpdk-dev] [PATCH v8 1/7] lib: add information metrics library Remy Horton @ 2017-01-17 23:24 ` Remy Horton 2017-01-17 23:24 ` [dpdk-dev] [PATCH v8 3/7] lib: add bitrate statistics library Remy Horton ` (5 subsequent siblings) 7 siblings, 0 replies; 115+ messages in thread From: Remy Horton @ 2017-01-17 23:24 UTC (permalink / raw) To: dev; +Cc: Reshma Pattan, Thomas Monjalon From: Reshma Pattan <reshma.pattan@intel.com> Modify the dpdk-procinfo process to display the newly added metrics. Added new command line option "--metrics" to display metrics. Signed-off-by: Reshma Pattan <reshma.pattan@intel.com> Signed-off-by: Remy Horton <remy.horton@intel.com> --- app/proc_info/main.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 73 insertions(+), 1 deletion(-) diff --git a/app/proc_info/main.c b/app/proc_info/main.c index 2c56d10..64fa2d3 100644 --- a/app/proc_info/main.c +++ b/app/proc_info/main.c @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2010-2016 Intel Corporation. All rights reserved. + * Copyright(c) 2010-2017 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -57,6 +57,7 @@ #include <rte_atomic.h> #include <rte_branch_prediction.h> #include <rte_string_fns.h> +#include <rte_metrics.h> /* Maximum long option length for option parsing. */ #define MAX_LONG_OPT_SZ 64 @@ -68,6 +69,8 @@ static uint32_t enabled_port_mask; static uint32_t enable_stats; /**< Enable xstats. */ static uint32_t enable_xstats; +/**< Enable metrics. */ +static uint32_t enable_metrics; /**< Enable stats reset. */ static uint32_t reset_stats; /**< Enable xstats reset. */ @@ -85,6 +88,8 @@ proc_info_usage(const char *prgname) " --stats: to display port statistics, enabled by default\n" " --xstats: to display extended port statistics, disabled by " "default\n" + " --metrics: to display derived metrics of the ports, disabled by " + "default\n" " --stats-reset: to reset port statistics\n" " --xstats-reset: to reset port extended statistics\n", prgname); @@ -127,6 +132,7 @@ proc_info_parse_args(int argc, char **argv) {"stats", 0, NULL, 0}, {"stats-reset", 0, NULL, 0}, {"xstats", 0, NULL, 0}, + {"metrics", 0, NULL, 0}, {"xstats-reset", 0, NULL, 0}, {NULL, 0, 0, 0} }; @@ -159,6 +165,10 @@ proc_info_parse_args(int argc, char **argv) else if (!strncmp(long_option[option_index].name, "xstats", MAX_LONG_OPT_SZ)) enable_xstats = 1; + else if (!strncmp(long_option[option_index].name, + "metrics", + MAX_LONG_OPT_SZ)) + enable_metrics = 1; /* Reset stats */ if (!strncmp(long_option[option_index].name, "stats-reset", MAX_LONG_OPT_SZ)) @@ -301,6 +311,62 @@ nic_xstats_clear(uint8_t port_id) printf("\n NIC extended statistics for port %d cleared\n", port_id); } +static void +metrics_display(int port_id) +{ + struct rte_metric_value *metrics; + struct rte_metric_name *names; + int len, ret; + static const char *nic_stats_border = "########################"; + + len = rte_metrics_get_names(NULL, 0); + if (len < 0) { + printf("Cannot get metrics count\n"); + return; + } + + metrics = rte_malloc(NULL, sizeof(struct rte_metric_value) * len, 0); + if (metrics == NULL) { + printf("Cannot allocate memory for metrics\n"); + return; + } + + names = rte_malloc(NULL, sizeof(struct rte_metric_name) * len, 0); + if (names == NULL) { + printf("Cannot allocate memory for metrcis names\n"); + rte_free(metrics); + return; + } + + if (len != rte_metrics_get_names(names, len)) { + printf("Cannot get metrics names\n"); + rte_free(metrics); + rte_free(names); + return; + } + + if (port_id == RTE_METRICS_GLOBAL) + printf("###### Non port specific metrics #########\n"); + else + printf("###### metrics for port %-2d #########\n", port_id); + printf("%s############################\n", nic_stats_border); + ret = rte_metrics_get_values(port_id, metrics, len); + if (ret < 0 || ret > len) { + printf("Cannot get metrics values\n"); + rte_free(metrics); + rte_free(names); + return; + } + + int i; + for (i = 0; i < len; i++) + printf("%s: %"PRIu64"\n", names[i].name, metrics[i].value); + + printf("%s############################\n", nic_stats_border); + rte_free(metrics); + rte_free(names); +} + int main(int argc, char **argv) { @@ -360,8 +426,14 @@ main(int argc, char **argv) nic_stats_clear(i); else if (reset_xstats) nic_xstats_clear(i); + else if (enable_metrics) + metrics_display(i); } } + /* print port independent stats */ + if (enable_metrics) + metrics_display(RTE_METRICS_GLOBAL); + return 0; } -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v8 3/7] lib: add bitrate statistics library 2017-01-17 23:24 ` [dpdk-dev] [PATCH v8 0/7] Expanded statistics reporting Remy Horton 2017-01-17 23:24 ` [dpdk-dev] [PATCH v8 1/7] lib: add information metrics library Remy Horton 2017-01-17 23:24 ` [dpdk-dev] [PATCH v8 2/7] app/proc_info: add metrics displaying Remy Horton @ 2017-01-17 23:24 ` Remy Horton 2017-01-17 23:24 ` [dpdk-dev] [PATCH v8 4/7] app/test-pmd: add bitrate statistics calculation Remy Horton ` (4 subsequent siblings) 7 siblings, 0 replies; 115+ messages in thread From: Remy Horton @ 2017-01-17 23:24 UTC (permalink / raw) To: dev; +Cc: Thomas Monjalon This patch adds a library that calculates peak and average data-rate statistics. For ethernet devices. These statistics are reported using the metrics library. Signed-off-by: Remy Horton <remy.horton@intel.com> --- MAINTAINERS | 4 + config/common_base | 5 + doc/api/doxy-api-index.md | 1 + doc/api/doxy-api.conf | 1 + doc/guides/rel_notes/release_17_02.rst | 5 + lib/Makefile | 1 + lib/librte_bitratestats/Makefile | 53 +++++++++ lib/librte_bitratestats/rte_bitrate.c | 132 +++++++++++++++++++++ lib/librte_bitratestats/rte_bitrate.h | 80 +++++++++++++ .../rte_bitratestats_version.map | 9 ++ mk/rte.app.mk | 1 + 11 files changed, 292 insertions(+) create mode 100644 lib/librte_bitratestats/Makefile create mode 100644 lib/librte_bitratestats/rte_bitrate.c create mode 100644 lib/librte_bitratestats/rte_bitrate.h create mode 100644 lib/librte_bitratestats/rte_bitratestats_version.map diff --git a/MAINTAINERS b/MAINTAINERS index 95836a2..d9423cb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -600,6 +600,10 @@ Metrics M: Remy Horton <remy.horton@intel.com> F: lib/librte_metrics/ +Bit-rate statistica +M: Remy Horton <remy.horton@intel.com> +F: lib/librte_bitratestats/ + Test Applications ----------------- diff --git a/config/common_base b/config/common_base index 0eb3866..decebe5 100644 --- a/config/common_base +++ b/config/common_base @@ -598,3 +598,8 @@ CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n # Compile the device metrics library # CONFIG_RTE_LIBRTE_METRICS=y + +# +# Compile the bitrate statistics library +# +CONFIG_RTE_LIBRTE_BITRATE=y diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md index 94f0f69..5e194b0 100644 --- a/doc/api/doxy-api-index.md +++ b/doc/api/doxy-api-index.md @@ -151,4 +151,5 @@ There are many libraries, so their headers may be grouped by topics: [ABI compat] (@ref rte_compat.h), [keepalive] (@ref rte_keepalive.h), [Device Metrics] (@ref rte_metrics.h), + [Bitrate Statistics] (@ref rte_bitrate.h), [version] (@ref rte_version.h) diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf index 194b670..6e6ab5c 100644 --- a/doc/api/doxy-api.conf +++ b/doc/api/doxy-api.conf @@ -35,6 +35,7 @@ INPUT = doc/api/doxy-api-index.md \ lib/librte_eal/common/include \ lib/librte_eal/common/include/generic \ lib/librte_acl \ + lib/librte_bitratestats \ lib/librte_cfgfile \ lib/librte_cmdline \ lib/librte_compat \ diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst index 4fca29b..44012c8 100644 --- a/doc/guides/rel_notes/release_17_02.rst +++ b/doc/guides/rel_notes/release_17_02.rst @@ -40,6 +40,11 @@ New Features intended to provide a reporting mechanism that is independent of the ethdev library. + * **Added bit-rate calculation library.** + + A library that can be used to calculate device bit-rates. Calculated + bitrates are reported using the metrics library. + This section is a comment. do not overwrite or remove it. Also, make sure to start the actual text at the margin. ========================================================= diff --git a/lib/Makefile b/lib/Makefile index 5d85dcf..e211bc0 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -59,6 +59,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += librte_pipeline DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics +DIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += librte_bitratestats ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni diff --git a/lib/librte_bitratestats/Makefile b/lib/librte_bitratestats/Makefile new file mode 100644 index 0000000..743b62c --- /dev/null +++ b/lib/librte_bitratestats/Makefile @@ -0,0 +1,53 @@ +# BSD LICENSE +# +# Copyright(c) 2016-2017 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +include $(RTE_SDK)/mk/rte.vars.mk + +# library name +LIB = librte_bitratestats.a + +CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) + +EXPORT_MAP := rte_bitratestats_version.map + +LIBABIVER := 1 + +# all source are stored in SRCS-y +SRCS-$(CONFIG_RTE_LIBRTE_BITRATE) := rte_bitrate.c + +# Install header file +SYMLINK-$(CONFIG_RTE_LIBRTE_BITRATE)-include += rte_bitrate.h + +DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_eal +DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_ether +DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_metrics + +include $(RTE_SDK)/mk/rte.lib.mk diff --git a/lib/librte_bitratestats/rte_bitrate.c b/lib/librte_bitratestats/rte_bitrate.c new file mode 100644 index 0000000..2c20272 --- /dev/null +++ b/lib/librte_bitratestats/rte_bitrate.c @@ -0,0 +1,132 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016-2017 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <rte_common.h> +#include <rte_ethdev.h> +#include <rte_malloc.h> +#include <rte_metrics.h> +#include <rte_bitrate.h> + +/* + * Persistent bit-rate data. + * @internal + */ +struct rte_stats_bitrate { + uint64_t last_ibytes; + uint64_t last_obytes; + uint64_t peak_ibits; + uint64_t peak_obits; + uint64_t ewma_ibits; + uint64_t ewma_obits; +}; + +struct rte_stats_bitrates { + struct rte_stats_bitrate port_stats[RTE_MAX_ETHPORTS]; + uint16_t id_stats_set; +}; + +struct rte_stats_bitrates * +rte_stats_bitrate_create(void) +{ + return rte_zmalloc(NULL, sizeof(struct rte_stats_bitrates), + RTE_CACHE_LINE_SIZE); +} + +int +rte_stats_bitrate_reg(struct rte_stats_bitrates *bitrate_data) +{ + const char * const names[] = { + "mean_bits_in", "mean_bits_out", + "peak_bits_in", "peak_bits_out", + }; + int return_value; + + return_value = rte_metrics_reg_names(&names[0], 4); + if (return_value >= 0) + bitrate_data->id_stats_set = return_value; + return return_value; +} + +int +rte_stats_bitrate_calc(struct rte_stats_bitrates *bitrate_data, + uint8_t port_id) +{ + struct rte_stats_bitrate *port_data; + struct rte_eth_stats eth_stats; + int ret_code; + uint64_t cnt_bits; + int64_t delta; + const int64_t alpha_percent = 20; + uint64_t values[4]; + + ret_code = rte_eth_stats_get(port_id, ð_stats); + if (ret_code != 0) + return ret_code; + + port_data = &bitrate_data->port_stats[port_id]; + + /* Incoming bitrate. This is an iteratively calculated EWMA + * (Expomentially Weighted Moving Average) that uses a + * weighting factor of alpha_percent. + */ + cnt_bits = (eth_stats.ibytes - port_data->last_ibytes) << 3; + port_data->last_ibytes = eth_stats.ibytes; + if (cnt_bits > port_data->peak_ibits) + port_data->peak_ibits = cnt_bits; + delta = cnt_bits; + delta -= port_data->ewma_ibits; + /* The +-50 fixes integer rounding during divison */ + if (delta > 0) + delta = (delta * alpha_percent + 50) / 100; + else + delta = (delta * alpha_percent - 50) / 100; + port_data->ewma_ibits += delta; + + /* Outgoing bitrate (also EWMA) */ + cnt_bits = (eth_stats.obytes - port_data->last_obytes) << 3; + port_data->last_obytes = eth_stats.obytes; + if (cnt_bits > port_data->peak_obits) + port_data->peak_obits = cnt_bits; + delta = cnt_bits; + delta -= port_data->ewma_obits; + delta = (delta * alpha_percent + 50) / 100; + port_data->ewma_obits += delta; + + values[0] = port_data->ewma_ibits; + values[1] = port_data->ewma_obits; + values[2] = port_data->peak_ibits; + values[3] = port_data->peak_obits; + rte_metrics_update_values(port_id, bitrate_data->id_stats_set, + values, 4); + return 0; +} diff --git a/lib/librte_bitratestats/rte_bitrate.h b/lib/librte_bitratestats/rte_bitrate.h new file mode 100644 index 0000000..564e4f7 --- /dev/null +++ b/lib/librte_bitratestats/rte_bitrate.h @@ -0,0 +1,80 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016-2017 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +/** + * Bitrate statistics data structure. + * This data structure is intentionally opaque. + */ +struct rte_stats_bitrates; + + +/** + * Allocate a bitrate statistics structure + * + * @return + * - Pointer to structure on success + * - NULL on error (zmalloc failure) + */ +struct rte_stats_bitrates *rte_stats_bitrate_create(void); + + +/** + * Register bitrate statistics with the metric library. + * + * @param bitrate_data + * Pointer allocated by rte_stats_create() + * + * @return + * Zero on success + * Negative on error + */ +int rte_stats_bitrate_reg(struct rte_stats_bitrates *bitrate_data); + + +/** + * Calculate statistics for current time window. The period with which + * this function is called should be the intended sampling window width. + * + * @param bitrate_data + * Bitrate statistics data pointer + * + * @param port_id + * Port id to calculate statistics for + * + * @return + * - Zero on success + * - Negative value on error + */ +int rte_stats_bitrate_calc(struct rte_stats_bitrates *bitrate_data, + uint8_t port_id); diff --git a/lib/librte_bitratestats/rte_bitratestats_version.map b/lib/librte_bitratestats/rte_bitratestats_version.map new file mode 100644 index 0000000..66f232f --- /dev/null +++ b/lib/librte_bitratestats/rte_bitratestats_version.map @@ -0,0 +1,9 @@ +DPDK_17.02 { + global: + + rte_stats_bitrate_calc; + rte_stats_bitrate_create; + rte_stats_bitrate_reg; + + local: *; +}; diff --git a/mk/rte.app.mk b/mk/rte.app.mk index 40fcf33..6aac5ac 100644 --- a/mk/rte.app.mk +++ b/mk/rte.app.mk @@ -99,6 +99,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL) += -lrte_eal _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE) += -lrte_cmdline _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE) += -lrte_cfgfile _LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS) += -lrte_metrics +_LDLIBS-$(CONFIG_RTE_LIBRTE_BITRATE) += -lrte_bitratestats _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += -lrte_pmd_bond -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v8 4/7] app/test-pmd: add bitrate statistics calculation 2017-01-17 23:24 ` [dpdk-dev] [PATCH v8 0/7] Expanded statistics reporting Remy Horton ` (2 preceding siblings ...) 2017-01-17 23:24 ` [dpdk-dev] [PATCH v8 3/7] lib: add bitrate statistics library Remy Horton @ 2017-01-17 23:24 ` Remy Horton 2017-01-17 23:24 ` [dpdk-dev] [PATCH v8 5/7] mbuf: add a timestamp to the mbuf for latencystats Remy Horton ` (3 subsequent siblings) 7 siblings, 0 replies; 115+ messages in thread From: Remy Horton @ 2017-01-17 23:24 UTC (permalink / raw) To: dev; +Cc: Thomas Monjalon Calculate bitrate statistics using the bitrate stats library. The resulting statistics can be viewed via proc_info. Signed-off-by: Remy Horton <remy.horton@intel.com> --- app/test-pmd/testpmd.c | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c index bfb2f8e..de60c09 100644 --- a/app/test-pmd/testpmd.c +++ b/app/test-pmd/testpmd.c @@ -1,7 +1,7 @@ /*- * BSD LICENSE * - * Copyright(c) 2010-2016 Intel Corporation. All rights reserved. + * Copyright(c) 2010-2017 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -79,6 +79,10 @@ #include <rte_pdump.h> #endif #include <rte_flow.h> +#include <rte_metrics.h> +#ifdef RTE_LIBRTE_BITRATE +#include <rte_bitrate.h> +#endif #include "testpmd.h" @@ -323,6 +327,9 @@ uint16_t nb_rx_queue_stats_mappings = 0; unsigned max_socket = 0; +/* Bitrate statistics */ +struct rte_stats_bitrates *bitrate_data; + /* Forward function declarations */ static void map_port_queue_stats_mapping_registers(uint8_t pi, struct rte_port *port); static void check_all_ports_link_status(uint32_t port_mask); @@ -922,12 +929,32 @@ run_pkt_fwd_on_lcore(struct fwd_lcore *fc, packet_fwd_t pkt_fwd) struct fwd_stream **fsm; streamid_t nb_fs; streamid_t sm_id; +#ifdef RTE_LIBRTE_BITRATE + uint64_t tics_per_1sec; + uint64_t tics_datum; + uint64_t tics_current; + uint8_t idx_port, cnt_ports; +#endif +#ifdef RTE_LIBRTE_BITRATE + cnt_ports = rte_eth_dev_count(); + tics_datum = rte_rdtsc(); + tics_per_1sec = rte_get_timer_hz(); +#endif fsm = &fwd_streams[fc->stream_idx]; nb_fs = fc->stream_nb; do { for (sm_id = 0; sm_id < nb_fs; sm_id++) (*pkt_fwd)(fsm[sm_id]); +#ifdef RTE_LIBRTE_BITRATE + tics_current = rte_rdtsc(); + if (tics_current - tics_datum >= tics_per_1sec) { + /* Periodic bitrate calculation */ + for (idx_port = 0; idx_port < cnt_ports; idx_port++) + rte_stats_bitrate_calc(bitrate_data, idx_port); + tics_datum = tics_current; + } +#endif } while (! fc->stopped); } @@ -2139,6 +2166,15 @@ main(int argc, char** argv) FOREACH_PORT(port_id, ports) rte_eth_promiscuous_enable(port_id); + /* Setup bitrate stats */ +#ifdef RTE_LIBRTE_BITRATE + bitrate_data = rte_stats_bitrate_create(); + if (bitrate_data == NULL) + rte_exit(EXIT_FAILURE, "Could not allocate bitrate data.\n"); + rte_stats_bitrate_reg(bitrate_data); +#endif + + #ifdef RTE_LIBRTE_CMDLINE if (interactive == 1) { if (auto_start) { -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v8 5/7] mbuf: add a timestamp to the mbuf for latencystats 2017-01-17 23:24 ` [dpdk-dev] [PATCH v8 0/7] Expanded statistics reporting Remy Horton ` (3 preceding siblings ...) 2017-01-17 23:24 ` [dpdk-dev] [PATCH v8 4/7] app/test-pmd: add bitrate statistics calculation Remy Horton @ 2017-01-17 23:24 ` Remy Horton 2017-01-17 23:24 ` [dpdk-dev] [PATCH v8 6/7] lib: added new library for latency stats Remy Horton ` (2 subsequent siblings) 7 siblings, 0 replies; 115+ messages in thread From: Remy Horton @ 2017-01-17 23:24 UTC (permalink / raw) To: dev; +Cc: Harry van Haaren, Thomas Monjalon, Reshma Pattan From: Harry van Haaren <harry.van.haaren@intel.com> This commit adds a uint64_t to the mbuf struct, allowing collection of latency and jitter statistics by measuring packet I/O timestamps. This change is required by the latencystats library. Signed-off-by: Reshma Pattan <reshma.pattan@intel.com> Signed-off-by: Harry van Haaren <harry.van.haaren@intel.com> --- lib/librte_mbuf/rte_mbuf.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h index bfce9f4..c35ba0a 100644 --- a/lib/librte_mbuf/rte_mbuf.h +++ b/lib/librte_mbuf/rte_mbuf.h @@ -512,6 +512,9 @@ struct rte_mbuf { /** Timesync flags for use with IEEE1588. */ uint16_t timesync; + + /** Timestamp for measuring latency. */ + uint64_t timestamp; } __rte_cache_aligned; /** -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v8 6/7] lib: added new library for latency stats 2017-01-17 23:24 ` [dpdk-dev] [PATCH v8 0/7] Expanded statistics reporting Remy Horton ` (4 preceding siblings ...) 2017-01-17 23:24 ` [dpdk-dev] [PATCH v8 5/7] mbuf: add a timestamp to the mbuf for latencystats Remy Horton @ 2017-01-17 23:24 ` Remy Horton 2017-01-17 23:24 ` [dpdk-dev] [PATCH v8 7/7] app/test-pmd: add latency statistics calculation Remy Horton 2017-01-18 15:05 ` [dpdk-dev] [PATCH v9 0/7] Expanded statistics reporting Remy Horton 7 siblings, 0 replies; 115+ messages in thread From: Remy Horton @ 2017-01-17 23:24 UTC (permalink / raw) To: dev; +Cc: Harry van Haaren, Thomas Monjalon, Reshma Pattan From: Harry van Haaren <harry.van.haaren@intel.com> Signed-off-by: Reshma Pattan <reshma.pattan@intel.com> Signed-off-by: Remy Horton <remy.horton@intel.com> Signed-off-by: Harry van Haaren <harry.van.haaren@intel.com> --- v7 to v8 changes: - CYCLES_PER_NS now a static inline function - "hidden" pthread creation now has polling API instead. The application must call rte_latencystats_update() to refresh the values. - Struct declarations and variable definitions cleaned up - Double initialization of the library now returns -EEXIST - MAINTAINERS entry in correct section - License year updates --- MAINTAINERS | 4 + config/common_base | 5 + doc/api/doxy-api-index.md | 1 + doc/api/doxy-api.conf | 1 + doc/guides/rel_notes/release_17_02.rst | 5 + lib/Makefile | 1 + lib/librte_latencystats/Makefile | 56 ++++ lib/librte_latencystats/rte_latencystats.c | 366 +++++++++++++++++++++ lib/librte_latencystats/rte_latencystats.h | 154 +++++++++ .../rte_latencystats_version.map | 10 + mk/rte.app.mk | 2 +- 11 files changed, 604 insertions(+), 1 deletion(-) create mode 100644 lib/librte_latencystats/Makefile create mode 100644 lib/librte_latencystats/rte_latencystats.c create mode 100644 lib/librte_latencystats/rte_latencystats.h create mode 100644 lib/librte_latencystats/rte_latencystats_version.map diff --git a/MAINTAINERS b/MAINTAINERS index d9423cb..03f53b7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -604,6 +604,10 @@ Bit-rate statistica M: Remy Horton <remy.horton@intel.com> F: lib/librte_bitratestats/ +Latency Stats +M: Reshma Pattan <reshma.pattan@intel.com> +F: lib/librte_latencystats/ + Test Applications ----------------- diff --git a/config/common_base b/config/common_base index decebe5..762a54c 100644 --- a/config/common_base +++ b/config/common_base @@ -603,3 +603,8 @@ CONFIG_RTE_LIBRTE_METRICS=y # Compile the bitrate statistics library # CONFIG_RTE_LIBRTE_BITRATE=y + +# +# Compile the latency statistics library +# +CONFIG_RTE_LIBRTE_LATENCY_STATS=y diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md index 5e194b0..1cacacc 100644 --- a/doc/api/doxy-api-index.md +++ b/doc/api/doxy-api-index.md @@ -152,4 +152,5 @@ There are many libraries, so their headers may be grouped by topics: [keepalive] (@ref rte_keepalive.h), [Device Metrics] (@ref rte_metrics.h), [Bitrate Statistics] (@ref rte_bitrate.h), + [Latency stats] (@ref rte_latencystats.h), [version] (@ref rte_version.h) diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf index 6e6ab5c..0effece 100644 --- a/doc/api/doxy-api.conf +++ b/doc/api/doxy-api.conf @@ -47,6 +47,7 @@ INPUT = doc/api/doxy-api-index.md \ lib/librte_jobstats \ lib/librte_kni \ lib/librte_kvargs \ + lib/librte_latencystats \ lib/librte_lpm \ lib/librte_mbuf \ lib/librte_mempool \ diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst index 44012c8..29bbd74 100644 --- a/doc/guides/rel_notes/release_17_02.rst +++ b/doc/guides/rel_notes/release_17_02.rst @@ -68,6 +68,10 @@ New Features Six new APIs have been added to the ixgbe PMD for MACsec offload support. The declarations for the APIs can be found in ``rte_pmd_ixgbe.h``. +* **Added latency stats library.** + + A library that measures packet latency. The collected statistics are jitter + and latency. For latency the minimum, average, and maximum is measured. Resolved Issues --------------- @@ -184,6 +188,7 @@ The libraries prepended with a plus sign were incremented in this version. librte_jobstats.so.1 librte_kni.so.2 librte_kvargs.so.1 + + librte_latencystats.so.1 librte_lpm.so.2 librte_mbuf.so.2 librte_mempool.so.2 diff --git a/lib/Makefile b/lib/Makefile index e211bc0..6fffa88 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -60,6 +60,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics DIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += librte_bitratestats +DIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += librte_latencystats ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni diff --git a/lib/librte_latencystats/Makefile b/lib/librte_latencystats/Makefile new file mode 100644 index 0000000..fd145d3 --- /dev/null +++ b/lib/librte_latencystats/Makefile @@ -0,0 +1,56 @@ +# BSD LICENSE +# +# Copyright(c) 2016-2017 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +include $(RTE_SDK)/mk/rte.vars.mk + +# library name +LIB = librte_latencystats.a + +CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3 +LDLIBS += -lm +LDLIBS += -lpthread + +EXPORT_MAP := rte_latencystats_version.map + +LIBABIVER := 1 + +# all source are stored in SRCS-y +SRCS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) := rte_latencystats.c + +# install this header file +SYMLINK-$(CONFIG_RTE_LIBRTE_LATENCY_STATS)-include := rte_latencystats.h + +# this lib depends upon: +DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_mbuf +DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_eal +DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_ether +DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_metrics + +include $(RTE_SDK)/mk/rte.lib.mk diff --git a/lib/librte_latencystats/rte_latencystats.c b/lib/librte_latencystats/rte_latencystats.c new file mode 100644 index 0000000..5334b8b --- /dev/null +++ b/lib/librte_latencystats/rte_latencystats.c @@ -0,0 +1,366 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016-2017 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <unistd.h> +#include <sys/types.h> +#include <stdbool.h> +#include <math.h> + +#include <rte_mbuf.h> +#include <rte_log.h> +#include <rte_cycles.h> +#include <rte_ethdev.h> +#include <rte_metrics.h> +#include <rte_memzone.h> +#include <rte_lcore.h> +#include <rte_timer.h> + +#include "rte_latencystats.h" + +/** Nano seconds per second */ +#define NS_PER_SEC 1E9 + +/** Clock cycles per nano second */ +static uint64_t +latencystat_cycles_per_ns(void) +{ + return rte_get_timer_hz() / NS_PER_SEC; +} + +/* Macros for printing using RTE_LOG */ +#define RTE_LOGTYPE_LATENCY_STATS RTE_LOGTYPE_USER1 + +static const char *MZ_RTE_LATENCY_STATS = "rte_latencystats"; +static int latency_stats_index; +static uint64_t samp_intvl; +static uint64_t timer_tsc; +static uint64_t prev_tsc; + +struct rte_latency_stats { + float min_latency; /**< Minimum latency in nano seconds */ + float avg_latency; /**< Average latency in nano seconds */ + float max_latency; /**< Maximum latency in nano seconds */ + float jitter; /** Latency variation */ +}; + +static struct rte_latency_stats *glob_stats; + +struct rxtx_cbs { + struct rte_eth_rxtx_callback *cb; +}; + +static struct rxtx_cbs rx_cbs[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT]; +static struct rxtx_cbs tx_cbs[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT]; + +struct latency_stats_nameoff { + char name[RTE_ETH_XSTATS_NAME_SIZE]; + unsigned int offset; +}; + +static const struct latency_stats_nameoff lat_stats_strings[] = { + {"min_latency_ns", offsetof(struct rte_latency_stats, min_latency)}, + {"avg_latency_ns", offsetof(struct rte_latency_stats, avg_latency)}, + {"max_latency_ns", offsetof(struct rte_latency_stats, max_latency)}, + {"jitter_ns", offsetof(struct rte_latency_stats, jitter)}, +}; + +#define NUM_LATENCY_STATS (sizeof(lat_stats_strings) / \ + sizeof(lat_stats_strings[0])) + +int32_t +rte_latencystats_update(void) +{ + unsigned int i; + float *stats_ptr = NULL; + uint64_t values[NUM_LATENCY_STATS] = {0}; + int ret; + + for (i = 0; i < NUM_LATENCY_STATS; i++) { + stats_ptr = RTE_PTR_ADD(glob_stats, + lat_stats_strings[i].offset); + values[i] = (uint64_t)floor((*stats_ptr)/ + latencystat_cycles_per_ns()); + } + + ret = rte_metrics_update_values(RTE_METRICS_GLOBAL, + latency_stats_index, + values, NUM_LATENCY_STATS); + if (ret < 0) + RTE_LOG(INFO, LATENCY_STATS, "Failed to push the stats\n"); + + return ret; +} + +static void +rte_latencystats_fill_values(struct rte_metric_value *values) +{ + unsigned int i; + float *stats_ptr = NULL; + + for (i = 0; i < NUM_LATENCY_STATS; i++) { + stats_ptr = RTE_PTR_ADD(glob_stats, + lat_stats_strings[i].offset); + values[i].key = i; + values[i].value = (uint64_t)floor((*stats_ptr)/ + latencystat_cycles_per_ns()); + } +} + +static uint16_t +add_time_stamps(uint8_t pid __rte_unused, + uint16_t qid __rte_unused, + struct rte_mbuf **pkts, + uint16_t nb_pkts, + uint16_t max_pkts __rte_unused, + void *user_cb __rte_unused) +{ + unsigned int i; + uint64_t diff_tsc, now; + + /* + * For every sample interval, + * time stamp is marked on one received packet. + */ + now = rte_rdtsc(); + for (i = 0; i < nb_pkts; i++) { + diff_tsc = now - prev_tsc; + timer_tsc += diff_tsc; + if (timer_tsc >= samp_intvl) { + /* + * TBD: Mark the timestamp only + * if not already marked by the + * hardware or the PMD. + */ + pkts[i]->timestamp = now; + timer_tsc = 0; + } + prev_tsc = now; + now = rte_rdtsc(); + } + + return nb_pkts; +} + +static uint16_t +calc_latency(uint8_t pid __rte_unused, + uint16_t qid __rte_unused, + struct rte_mbuf **pkts, + uint16_t nb_pkts, + void *_ __rte_unused) +{ + unsigned int i, cnt = 0; + uint64_t now; + float latency[nb_pkts]; + static float prev_latency; + /* + * Alpha represents degree of weighting decrease in EWMA, + * a constant smoothing factor between 0 and 1. The value + * is used below for measuring average latency. + */ + const float alpha = 0.2; + + now = rte_rdtsc(); + for (i = 0; i < nb_pkts; i++) { + if (pkts[i]->timestamp) + latency[cnt++] = now - pkts[i]->timestamp; + } + + for (i = 0; i < cnt; i++) { + /* + * The jitter is calculated as statistical mean of interpacket + * delay variation. The "jitter estimate" is computed by taking + * the absolute values of the ipdv sequence and applying an + * exponential filter with parameter 1/16 to generate the + * estimate. i.e J=J+(|D(i-1,i)|-J)/16. Where J is jitter, + * D(i-1,i) is difference in latency of two consecutive packets + * i-1 and i. + * Reference: Calculated as per RFC 5481, sec 4.1, + * RFC 3393 sec 4.5, RFC 1889 sec. + */ + glob_stats->jitter += (abs(prev_latency - latency[i]) + - glob_stats->jitter)/16; + if (glob_stats->min_latency == 0) + glob_stats->min_latency = latency[i]; + else if (latency[i] < glob_stats->min_latency) + glob_stats->min_latency = latency[i]; + else if (latency[i] > glob_stats->max_latency) + glob_stats->max_latency = latency[i]; + /* + * The average latency is measured using exponential moving + * average, i.e. using EWMA + * https://en.wikipedia.org/wiki/Moving_average + */ + glob_stats->avg_latency += + alpha * (latency[i] - glob_stats->avg_latency); + prev_latency = latency[i]; + } + + return nb_pkts; +} + +int +rte_latencystats_init(uint64_t app_samp_intvl, + rte_latency_stats_flow_type_fn user_cb) +{ + unsigned int i; + uint8_t pid; + uint16_t qid; + struct rxtx_cbs *cbs = NULL; + const uint8_t nb_ports = rte_eth_dev_count(); + const char *ptr_strings[NUM_LATENCY_STATS] = {0}; + const struct rte_memzone *mz = NULL; + const unsigned int flags = 0; + + if (rte_memzone_lookup(MZ_RTE_LATENCY_STATS)) + return -EEXIST; + + /** Allocate stats in shared memory fo multi process support */ + mz = rte_memzone_reserve(MZ_RTE_LATENCY_STATS, sizeof(*glob_stats), + rte_socket_id(), flags); + if (mz == NULL) { + RTE_LOG(ERR, LATENCY_STATS, "Cannot reserve memory: %s:%d\n", + __func__, __LINE__); + return -ENOMEM; + } + + glob_stats = mz->addr; + samp_intvl = app_samp_intvl * latencystat_cycles_per_ns(); + + /** Register latency stats with stats library */ + for (i = 0; i < NUM_LATENCY_STATS; i++) + ptr_strings[i] = lat_stats_strings[i].name; + + latency_stats_index = rte_metrics_reg_names(ptr_strings, + NUM_LATENCY_STATS); + if (latency_stats_index < 0) { + RTE_LOG(DEBUG, LATENCY_STATS, + "Failed to register latency stats names\n"); + return -1; + } + + /** Register Rx/Tx callbacks */ + for (pid = 0; pid < nb_ports; pid++) { + struct rte_eth_dev_info dev_info; + rte_eth_dev_info_get(pid, &dev_info); + for (qid = 0; qid < dev_info.nb_rx_queues; qid++) { + cbs = &rx_cbs[pid][qid]; + cbs->cb = rte_eth_add_first_rx_callback(pid, qid, + add_time_stamps, user_cb); + if (!cbs->cb) + RTE_LOG(INFO, LATENCY_STATS, "Failed to " + "register Rx callback for pid=%d, " + "qid=%d\n", pid, qid); + } + for (qid = 0; qid < dev_info.nb_tx_queues; qid++) { + cbs = &tx_cbs[pid][qid]; + cbs->cb = rte_eth_add_tx_callback(pid, qid, + calc_latency, user_cb); + if (!cbs->cb) + RTE_LOG(INFO, LATENCY_STATS, "Failed to " + "register Tx callback for pid=%d, " + "qid=%d\n", pid, qid); + } + } + return 0; +} + +int +rte_latencystats_uninit(void) +{ + uint8_t pid; + uint16_t qid; + int ret = 0; + struct rxtx_cbs *cbs = NULL; + const uint8_t nb_ports = rte_eth_dev_count(); + + /** De register Rx/Tx callbacks */ + for (pid = 0; pid < nb_ports; pid++) { + struct rte_eth_dev_info dev_info; + rte_eth_dev_info_get(pid, &dev_info); + for (qid = 0; qid < dev_info.nb_rx_queues; qid++) { + cbs = &rx_cbs[pid][qid]; + ret = rte_eth_remove_rx_callback(pid, qid, cbs->cb); + if (ret) + RTE_LOG(INFO, LATENCY_STATS, "failed to " + "remove Rx callback for pid=%d, " + "qid=%d\n", pid, qid); + } + for (qid = 0; qid < dev_info.nb_tx_queues; qid++) { + cbs = &tx_cbs[pid][qid]; + ret = rte_eth_remove_tx_callback(pid, qid, cbs->cb); + if (ret) + RTE_LOG(INFO, LATENCY_STATS, "failed to " + "remove Tx callback for pid=%d, " + "qid=%d\n", pid, qid); + } + } + + return 0; +} + +int +rte_latencystats_get_names(struct rte_metric_name *names, uint16_t size) +{ + unsigned int i; + + if (names == NULL || size < NUM_LATENCY_STATS) + return NUM_LATENCY_STATS; + + for (i = 0; i < NUM_LATENCY_STATS; i++) + snprintf(names[i].name, sizeof(names[i].name), + "%s", lat_stats_strings[i].name); + + return NUM_LATENCY_STATS; +} + +int +rte_latencystats_get(struct rte_metric_value *values, uint16_t size) +{ + if (size < NUM_LATENCY_STATS || values == NULL) + return NUM_LATENCY_STATS; + + if (rte_eal_process_type() == RTE_PROC_SECONDARY) { + const struct rte_memzone *mz; + mz = rte_memzone_lookup(MZ_RTE_LATENCY_STATS); + if (mz == NULL) { + RTE_LOG(ERR, LATENCY_STATS, + "Latency stats memzone not found\n"); + return -ENOMEM; + } + glob_stats = mz->addr; + } + + /* Retrieve latency stats */ + rte_latencystats_fill_values(values); + + return NUM_LATENCY_STATS; +} diff --git a/lib/librte_latencystats/rte_latencystats.h b/lib/librte_latencystats/rte_latencystats.h new file mode 100644 index 0000000..28c6dcf --- /dev/null +++ b/lib/librte_latencystats/rte_latencystats.h @@ -0,0 +1,154 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016-2017 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _RTE_LATENCYSTATS_H_ +#define _RTE_LATENCYSTATS_H_ + +/** + * @file + * RTE latency stats + * + * library to provide application and flow based latency stats. + */ + +#include <rte_metrics.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Note: This function pointer is for future flow based latency stats + * implementation. + * + * Function type used for identifting flow types of a Rx packet. + * + * The callback function is called on Rx for each packet. + * This function is used for flow based latency calculations. + * + * @param pkt + * Packet that has to be identified with its flow types. + * @param user_param + * The arbitrary user parameter passed in by the application when + * the callback was originally configured. + * @return + * The flow_mask, representing the multiple flow types of a packet. + */ +typedef uint16_t (*rte_latency_stats_flow_type_fn)(struct rte_mbuf *pkt, + void *user_param); + +/** + * Registers Rx/Tx callbacks for each active port, queue. + * + * @param samp_intvl + * Sampling time period in nano seconds, at which packet + * should be marked with time stamp. + * @param user_cb + * Note: This param is for future flow based latency stats + * implementation. + * User callback to be called to get flow types of a packet. + * Used for flow based latency calculation. + * If the value is NULL, global stats will be calculated, + * else flow based latency stats will be calculated. + * For now just pass on the NULL value to this param. + * @return + * -1 : On error + * -ENOMEM: On error + * 0 : On success + */ +int rte_latencystats_init(uint64_t samp_intvl, + rte_latency_stats_flow_type_fn user_cb); + +/** + * Calculates the latency and jitter values internally, exposing the updated + * values via *rte_latencystats_get* or the rte_metrics API. + * @return: + * 0 : on Success + * < 0 : Error in updating values. + */ +int32_t rte_latencystats_update(void); + +/** + * Removes registered Rx/Tx callbacks for each active port, queue. + * + * @return + * -1: On error + * 0: On success + */ +int rte_latencystats_uninit(void); + +/** + * Retrieve names of latency statistics + * + * @param names + * Block of memory to insert names into. Must be at least size in capacity. + * If set to NULL, function returns required capacity. + * @param size + * Capacity of latency stats names (number of names). + * @return + * - positive value lower or equal to size: success. The return value + * is the number of entries filled in the stats table. + * - positive value higher than size: error, the given statistics table + * is too small. The return value corresponds to the size that should + * be given to succeed. The entries in the table are not valid and + * shall not be used by the caller. + */ +int rte_latencystats_get_names(struct rte_metric_name *names, + uint16_t size); + +/** + * Retrieve latency statistics. + * + * @param values + * A pointer to a table of structure of type *rte_metric_value* + * to be filled with latency statistics ids and values. + * This parameter can be set to NULL if size is 0. + * @param size + * The size of the stats table, which should be large enough to store + * all the latency stats. + * @return + * - positive value lower or equal to size: success. The return value + * is the number of entries filled in the stats table. + * - positive value higher than size: error, the given statistics table + * is too small. The return value corresponds to the size that should + * be given to succeed. The entries in the table are not valid and + * shall not be used by the caller. + * -ENOMEM: On failure. + */ +int rte_latencystats_get(struct rte_metric_value *values, + uint16_t size); + +#ifdef __cplusplus +} +#endif + +#endif /* _RTE_LATENCYSTATS_H_ */ diff --git a/lib/librte_latencystats/rte_latencystats_version.map b/lib/librte_latencystats/rte_latencystats_version.map new file mode 100644 index 0000000..502018e --- /dev/null +++ b/lib/librte_latencystats/rte_latencystats_version.map @@ -0,0 +1,10 @@ +DPDK_17.02 { + global: + + rte_latencystats_get; + rte_latencystats_get_names; + rte_latencystats_init; + rte_latencystats_uninit; + + local: *; +}; diff --git a/mk/rte.app.mk b/mk/rte.app.mk index 6aac5ac..1d36fad 100644 --- a/mk/rte.app.mk +++ b/mk/rte.app.mk @@ -100,7 +100,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE) += -lrte_cmdline _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE) += -lrte_cfgfile _LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS) += -lrte_metrics _LDLIBS-$(CONFIG_RTE_LIBRTE_BITRATE) += -lrte_bitratestats - +_LDLIBS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += -lrte_latencystats _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += -lrte_pmd_bond _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += -lrte_pmd_xenvirt -lxenstore -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v8 7/7] app/test-pmd: add latency statistics calculation 2017-01-17 23:24 ` [dpdk-dev] [PATCH v8 0/7] Expanded statistics reporting Remy Horton ` (5 preceding siblings ...) 2017-01-17 23:24 ` [dpdk-dev] [PATCH v8 6/7] lib: added new library for latency stats Remy Horton @ 2017-01-17 23:24 ` Remy Horton 2017-01-18 15:05 ` [dpdk-dev] [PATCH v9 0/7] Expanded statistics reporting Remy Horton 7 siblings, 0 replies; 115+ messages in thread From: Remy Horton @ 2017-01-17 23:24 UTC (permalink / raw) To: dev; +Cc: Harry van Haaren, Thomas Monjalon, Reshma Pattan From: Harry van Haaren <harry.van.haaren@intel.com> This patch adds latency stats commandline argument to testpmd, allowing to specify the lcore to use for latencystats updates. Signed-off-by: Reshma Pattan <reshma.pattan@intel.com> Signed-off-by: Harry van Haaren <harry.van.haaren@intel.com> Signed-off-by: Remy Horton <remy.horton@intel.com> --- v7 -> v8 changes: - add optarg to enable latencystats, and which core to use for polling. - implement polling of rte_latencystats_update() from lcore - license year updates --- app/test-pmd/parameters.c | 20 +++++++++++++++++++- app/test-pmd/testpmd.c | 37 +++++++++++++++++++++++++++++++++++++ app/test-pmd/testpmd.h | 6 +++++- 3 files changed, 61 insertions(+), 2 deletions(-) diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c index 28db8cd..30b60ba 100644 --- a/app/test-pmd/parameters.c +++ b/app/test-pmd/parameters.c @@ -1,7 +1,7 @@ /*- * BSD LICENSE * - * Copyright(c) 2010-2016 Intel Corporation. All rights reserved. + * Copyright(c) 2010-2017 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -149,6 +149,10 @@ usage(char* progname) "the packet will be enqueued into the rx drop-queue. " "If the drop-queue doesn't exist, the packet is dropped. " "By default drop-queue=127.\n"); +#ifdef RTE_LIBRTE_LATENCY_STATS + printf(" --latencystats=N: enable latency and jitter statistcs " + "monitoring on lcore id N.\n"); +#endif printf(" --crc-strip: enable CRC stripping by hardware.\n"); printf(" --enable-lro: enable large receive offload.\n"); printf(" --enable-rx-cksum: enable rx hardware checksum offload.\n"); @@ -526,6 +530,7 @@ launch_args_parse(int argc, char** argv) { "pkt-filter-report-hash", 1, 0, 0 }, { "pkt-filter-size", 1, 0, 0 }, { "pkt-filter-drop-queue", 1, 0, 0 }, + { "latencystats", 1, 0, 0 }, { "crc-strip", 0, 0, 0 }, { "enable-lro", 0, 0, 0 }, { "enable-rx-cksum", 0, 0, 0 }, @@ -766,6 +771,19 @@ launch_args_parse(int argc, char** argv) "drop queue %d invalid - must" "be >= 0 \n", n); } +#ifdef RTE_LIBRTE_LATENCY_STATS + if (!strcmp(lgopts[opt_idx].name, + "latencystats")) { + n = atoi(optarg); + if (n >= 0) { + latencystats_lcore_id = (lcoreid_t) n; + latencystats_enabled = 1; + } else + rte_exit(EXIT_FAILURE, + "invalid lcore id %d for latencystats" + " must be >= 0\n", n); + } +#endif if (!strcmp(lgopts[opt_idx].name, "crc-strip")) rx_mode.hw_strip_crc = 1; if (!strcmp(lgopts[opt_idx].name, "enable-lro")) diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c index de60c09..70218bc 100644 --- a/app/test-pmd/testpmd.c +++ b/app/test-pmd/testpmd.c @@ -83,6 +83,10 @@ #ifdef RTE_LIBRTE_BITRATE #include <rte_bitrate.h> #endif +#include <rte_metrics.h> +#ifdef RTE_LIBRTE_LATENCY_STATS +#include <rte_latencystats.h> +#endif #include "testpmd.h" @@ -276,6 +280,20 @@ uint32_t bypass_timeout = RTE_BYPASS_TMT_OFF; #endif +#ifdef RTE_LIBRTE_LATENCY_STATS + +/* + * Set when latency stats is enabled in the commandline + */ +uint8_t latencystats_enabled; + +/* + * Lcore ID to serive latency statistics. + */ +lcoreid_t latencystats_lcore_id = -1; + +#endif + /* * Ethernet device configuration. */ @@ -955,6 +973,11 @@ run_pkt_fwd_on_lcore(struct fwd_lcore *fc, packet_fwd_t pkt_fwd) tics_datum = tics_current; } #endif +#ifdef RTE_LIBRTE_LATENCY_STATS + if (latencystats_lcore_id == rte_lcore_id()) + rte_latencystats_update(); +#endif + } while (! fc->stopped); } @@ -2108,6 +2131,9 @@ signal_handler(int signum) /* uninitialize packet capture framework */ rte_pdump_uninit(); #endif +#ifdef RTE_LIBRTE_LATENCY_STATS + rte_latencystats_uninit(); +#endif force_quit(); /* exit with the expected status */ signal(signum, SIG_DFL); @@ -2166,6 +2192,17 @@ main(int argc, char** argv) FOREACH_PORT(port_id, ports) rte_eth_promiscuous_enable(port_id); +#ifdef RTE_LIBRTE_LATENCY_STATS + if (latencystats_enabled != 0) { + int ret = rte_latencystats_init(1, NULL); + if (ret) + printf("Warning: latencystats init()" + " returned error %d\n", ret); + printf("Latencystats running on lcore %d\n", + latencystats_lcore_id); + } +#endif + /* Setup bitrate stats */ #ifdef RTE_LIBRTE_BITRATE bitrate_data = rte_stats_bitrate_create(); diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h index 0a9a1af..35f7477 100644 --- a/app/test-pmd/testpmd.h +++ b/app/test-pmd/testpmd.h @@ -1,7 +1,7 @@ /*- * BSD LICENSE * - * Copyright(c) 2010-2016 Intel Corporation. All rights reserved. + * Copyright(c) 2010-2017 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -381,6 +381,10 @@ extern enum dcb_queue_mapping_mode dcb_q_mapping; extern uint16_t mbuf_data_size; /**< Mbuf data space size. */ extern uint32_t param_total_num_mbufs; + +extern uint8_t latencystats_enabled; +extern lcoreid_t latencystats_lcore_id; + extern struct rte_fdir_conf fdir_conf; /* -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v9 0/7] Expanded statistics reporting 2017-01-17 23:24 ` [dpdk-dev] [PATCH v8 0/7] Expanded statistics reporting Remy Horton ` (6 preceding siblings ...) 2017-01-17 23:24 ` [dpdk-dev] [PATCH v8 7/7] app/test-pmd: add latency statistics calculation Remy Horton @ 2017-01-18 15:05 ` Remy Horton 2017-01-18 15:05 ` [dpdk-dev] [PATCH v9 1/7] lib: add information metrics library Remy Horton ` (7 more replies) 7 siblings, 8 replies; 115+ messages in thread From: Remy Horton @ 2017-01-18 15:05 UTC (permalink / raw) To: dev; +Cc: Thomas Monjalon This patchset extends statistics reporting to include peak and average data-rate metrics. It comes in two parts: a statistics reporting library, and a bitrate calculation library that uses it. This structure is intended to seperate statistic reporting from ethdev and allow more flexible metric registration. -- v9 changes: * Updated .map files to reflect function changes in v8 * Fixed rte_malloc() of zero bytes in proc_info when no metrics exist * Fixed rte_metrics_init not being called explicitly in testpmd v8 changes: * Release notes correction * Updated copyright years * rte_metric_init() takes socket id & must be explicitly called * rte_metrics_reg_metric renamed to rte_metrics_reg_name() * rte_metrics_update_metric() renamed to rte_metrics_update_value() * Doxygen updates * Changed malloc()/free() to rte_malloc()/rte_free() * Removed redundant memset() * rte_stats_bitrates_s renamed to rte_stats_bitrates_s * Split mbuf change to own patch for visibility * CYCLES_PER_NS now a static inline function * latency: "hidden" pthread creation now has polling API instead. * Struct declarations and variable definitions cleaned up * Double initialization of the latency library now returns -EEXIST * MAINTAINERS entry for layenctstats in correct section v7 changes: * RTE_METRICS_NONPORT renamed to RTE_METRICS_GLOBAL * Multiple changes to rte_metrics.h doxygen documentation * Split apart latency patch into lib, test-pmd, & proc_info parts * Reordered patches by functionality * Insufficent capacity return value changed from -ERANGE to actual size * Cache alignment in bitrate library * Tightened up const usage to avoid STATIC_CONST_CHAR_ARRAY warning * Reshma reinstated as author for (now split) latency patch * Rebase to master v6 changes: * Metrics display now has "Non port specific" rather than "port -1" * Fixed sign issue in EWMA delta calculation * Rebased to master v5 changes: * Updated Shared Library Versions in release notes * Merged in Reshma's latencystats library v4 changes: * References to 16.11 changed to 17.02 * Fetching of non-port values was broken * Added sanity checks to value fetching * rte_stat_value renamed to rte_metric_value * Corrected doxygen descriptions * Added MAINTAINERS entries * Added #ifdef directives to bitrate code in test-pmd v3 changes: * Marked rte_stats_bitrate_s as internal * Minor integer roundoff correction * Coding style corrections * Removed spurious object allocation * Changes to rte_metrics.[ch] moved from Patch 2/3 to 1/3. * Reintroduced non-port values (RTE_METRICS_NONPORT) * Added spinlocks to metric library * Removed spurious test registration/update * Added release notes entries v2 changes: * Uses a new metrics library rather than being part of ethdev Harry van Haaren (3): mbuf: add a timestamp to the mbuf for latencystats lib: added new library for latency stats app/test-pmd: add latency statistics calculation Remy Horton (3): lib: add information metrics library lib: add bitrate statistics library app/test-pmd: add bitrate statistics calculation Reshma Pattan (1): app/proc_info: add metrics displaying MAINTAINERS | 12 + app/proc_info/main.c | 79 ++++- app/test-pmd/parameters.c | 20 +- app/test-pmd/testpmd.c | 78 ++++- app/test-pmd/testpmd.h | 6 +- config/common_base | 15 + doc/api/doxy-api-index.md | 3 + doc/api/doxy-api.conf | 3 + doc/guides/rel_notes/release_17_02.rst | 18 + lib/Makefile | 3 + lib/librte_bitratestats/Makefile | 53 +++ lib/librte_bitratestats/rte_bitrate.c | 132 ++++++++ lib/librte_bitratestats/rte_bitrate.h | 80 +++++ .../rte_bitratestats_version.map | 9 + lib/librte_latencystats/Makefile | 56 ++++ lib/librte_latencystats/rte_latencystats.c | 366 +++++++++++++++++++++ lib/librte_latencystats/rte_latencystats.h | 154 +++++++++ .../rte_latencystats_version.map | 11 + lib/librte_mbuf/rte_mbuf.h | 3 + lib/librte_metrics/Makefile | 51 +++ lib/librte_metrics/rte_metrics.c | 308 +++++++++++++++++ lib/librte_metrics/rte_metrics.h | 231 +++++++++++++ lib/librte_metrics/rte_metrics_version.map | 13 + mk/rte.app.mk | 3 + 24 files changed, 1703 insertions(+), 4 deletions(-) create mode 100644 lib/librte_bitratestats/Makefile create mode 100644 lib/librte_bitratestats/rte_bitrate.c create mode 100644 lib/librte_bitratestats/rte_bitrate.h create mode 100644 lib/librte_bitratestats/rte_bitratestats_version.map create mode 100644 lib/librte_latencystats/Makefile create mode 100644 lib/librte_latencystats/rte_latencystats.c create mode 100644 lib/librte_latencystats/rte_latencystats.h create mode 100644 lib/librte_latencystats/rte_latencystats_version.map create mode 100644 lib/librte_metrics/Makefile create mode 100644 lib/librte_metrics/rte_metrics.c create mode 100644 lib/librte_metrics/rte_metrics.h create mode 100644 lib/librte_metrics/rte_metrics_version.map -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v9 1/7] lib: add information metrics library 2017-01-18 15:05 ` [dpdk-dev] [PATCH v9 0/7] Expanded statistics reporting Remy Horton @ 2017-01-18 15:05 ` Remy Horton 2017-01-30 15:50 ` Thomas Monjalon 2017-01-18 15:05 ` [dpdk-dev] [PATCH v9 2/7] app/proc_info: add metrics displaying Remy Horton ` (6 subsequent siblings) 7 siblings, 1 reply; 115+ messages in thread From: Remy Horton @ 2017-01-18 15:05 UTC (permalink / raw) To: dev; +Cc: Thomas Monjalon This patch adds a new information metric library that allows other modules to register named metrics and update their values. It is intended to be independent of ethdev, rather than mixing ethdev and non-ethdev information in xstats. Signed-off-by: Remy Horton <remy.horton@intel.com> --- MAINTAINERS | 4 + config/common_base | 5 + doc/api/doxy-api-index.md | 1 + doc/api/doxy-api.conf | 1 + doc/guides/rel_notes/release_17_02.rst | 8 + lib/Makefile | 1 + lib/librte_metrics/Makefile | 51 +++++ lib/librte_metrics/rte_metrics.c | 308 +++++++++++++++++++++++++++++ lib/librte_metrics/rte_metrics.h | 231 ++++++++++++++++++++++ lib/librte_metrics/rte_metrics_version.map | 13 ++ mk/rte.app.mk | 2 + 11 files changed, 625 insertions(+) create mode 100644 lib/librte_metrics/Makefile create mode 100644 lib/librte_metrics/rte_metrics.c create mode 100644 lib/librte_metrics/rte_metrics.h create mode 100644 lib/librte_metrics/rte_metrics_version.map diff --git a/MAINTAINERS b/MAINTAINERS index 9645c9b..95836a2 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -596,6 +596,10 @@ F: lib/librte_jobstats/ F: examples/l2fwd-jobstats/ F: doc/guides/sample_app_ug/l2_forward_job_stats.rst +Metrics +M: Remy Horton <remy.horton@intel.com> +F: lib/librte_metrics/ + Test Applications ----------------- diff --git a/config/common_base b/config/common_base index 8e9dcfa..0eb3866 100644 --- a/config/common_base +++ b/config/common_base @@ -593,3 +593,8 @@ CONFIG_RTE_APP_TEST_RESOURCE_TAR=n CONFIG_RTE_TEST_PMD=y CONFIG_RTE_TEST_PMD_RECORD_CORE_CYCLES=n CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n + +# +# Compile the device metrics library +# +CONFIG_RTE_LIBRTE_METRICS=y diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md index 72d59b2..94f0f69 100644 --- a/doc/api/doxy-api-index.md +++ b/doc/api/doxy-api-index.md @@ -150,4 +150,5 @@ There are many libraries, so their headers may be grouped by topics: [common] (@ref rte_common.h), [ABI compat] (@ref rte_compat.h), [keepalive] (@ref rte_keepalive.h), + [Device Metrics] (@ref rte_metrics.h), [version] (@ref rte_version.h) diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf index b340fcf..194b670 100644 --- a/doc/api/doxy-api.conf +++ b/doc/api/doxy-api.conf @@ -50,6 +50,7 @@ INPUT = doc/api/doxy-api-index.md \ lib/librte_mbuf \ lib/librte_mempool \ lib/librte_meter \ + lib/librte_metrics \ lib/librte_net \ lib/librte_pdump \ lib/librte_pipeline \ diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst index 4a3b947..abbfe4a 100644 --- a/doc/guides/rel_notes/release_17_02.rst +++ b/doc/guides/rel_notes/release_17_02.rst @@ -34,6 +34,12 @@ New Features Refer to the previous release notes for examples. + * **Added information metric library.** + + A library that allows information metrics to be added and update. It is + intended to provide a reporting mechanism that is independent of the + ethdev library. + This section is a comment. do not overwrite or remove it. Also, make sure to start the actual text at the margin. ========================================================= @@ -205,6 +211,7 @@ The libraries prepended with a plus sign were incremented in this version. .. code-block:: diff librte_acl.so.2 + + librte_bitratestats.so.1 librte_cfgfile.so.2 librte_cmdline.so.2 librte_cryptodev.so.2 @@ -220,6 +227,7 @@ The libraries prepended with a plus sign were incremented in this version. librte_mbuf.so.2 librte_mempool.so.2 librte_meter.so.1 + + librte_metrics.so.1 librte_net.so.1 librte_pdump.so.1 librte_pipeline.so.3 diff --git a/lib/Makefile b/lib/Makefile index 990f23a..5d85dcf 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -58,6 +58,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_TABLE) += librte_table DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += librte_pipeline DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump +DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni diff --git a/lib/librte_metrics/Makefile b/lib/librte_metrics/Makefile new file mode 100644 index 0000000..8d6e23a --- /dev/null +++ b/lib/librte_metrics/Makefile @@ -0,0 +1,51 @@ +# BSD LICENSE +# +# Copyright(c) 2016 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +include $(RTE_SDK)/mk/rte.vars.mk + +# library name +LIB = librte_metrics.a + +CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) + +EXPORT_MAP := rte_metrics_version.map + +LIBABIVER := 1 + +# all source are stored in SRCS-y +SRCS-$(CONFIG_RTE_LIBRTE_METRICS) := rte_metrics.c + +# Install header file +SYMLINK-$(CONFIG_RTE_LIBRTE_METRICS)-include += rte_metrics.h + +DEPDIRS-$(CONFIG_RTE_LIBRTE_METRICS) += lib/librte_eal + +include $(RTE_SDK)/mk/rte.lib.mk diff --git a/lib/librte_metrics/rte_metrics.c b/lib/librte_metrics/rte_metrics.c new file mode 100644 index 0000000..5a67c85 --- /dev/null +++ b/lib/librte_metrics/rte_metrics.c @@ -0,0 +1,308 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016-2017 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <string.h> +#include <sys/queue.h> + +#include <rte_common.h> +#include <rte_malloc.h> +#include <rte_metrics.h> +#include <rte_lcore.h> +#include <rte_memzone.h> +#include <rte_spinlock.h> + +#define RTE_METRICS_MAX_METRICS 256 +#define RTE_METRICS_MEMZONE_NAME "RTE_METRICS" + +/** + * Internal stats metadata and value entry. + * + * @internal + * @param name + * Name of metric + * @param value + * Current value for metric + * @param idx_next_set + * Index of next root element (zero for none) + * @param idx_next_metric + * Index of next metric in set (zero for none) + * + * Only the root of each set needs idx_next_set but since it has to be + * assumed that number of sets could equal total number of metrics, + * having a separate set metadata table doesn't save any memory. + */ +struct rte_metrics_meta_s { + char name[RTE_METRICS_MAX_NAME_LEN]; + uint64_t value[RTE_MAX_ETHPORTS]; + uint64_t nonport_value; + uint16_t idx_next_set; + uint16_t idx_next_stat; +}; + +/** + * Internal stats info structure. + * + * @internal + * @param idx_last_set + * Index of last metadata entry with valid data. This value is + * not valid if cnt_stats is zero. + * @param cnt_stats + * Number of metrics. + * @param metadata + * Stat data memory block. + * + * Offsets into metadata are used instead of pointers because ASLR + * means that having the same physical addresses in different + * processes is not guaranteed. + */ +struct rte_metrics_data_s { + uint16_t idx_last_set; + uint16_t cnt_stats; + struct rte_metrics_meta_s metadata[RTE_METRICS_MAX_METRICS]; + rte_spinlock_t lock; +}; + +void +rte_metrics_init(int socket_id) +{ + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + + if (rte_eal_process_type() != RTE_PROC_PRIMARY) + return; + + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); + if (memzone != NULL) + return; + memzone = rte_memzone_reserve(RTE_METRICS_MEMZONE_NAME, + sizeof(struct rte_metrics_data_s), socket_id, 0); + if (memzone == NULL) + rte_exit(EXIT_FAILURE, "Unable to allocate stats memzone\n"); + stats = memzone->addr; + memset(stats, 0, sizeof(struct rte_metrics_data_s)); + rte_spinlock_init(&stats->lock); +} + +int +rte_metrics_reg_name(const char *name) +{ + const char * const list_names[] = {name}; + + return rte_metrics_reg_names(list_names, 1); +} + +int +rte_metrics_reg_names(const char * const *names, uint16_t cnt_names) +{ + struct rte_metrics_meta_s *entry; + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + uint16_t idx_name; + uint16_t idx_base; + + /* Some sanity checks */ + if (cnt_names < 1 || names == NULL) + return -EINVAL; + + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); + if (memzone == NULL) + return -EIO; + stats = memzone->addr; + + if (stats->cnt_stats + cnt_names >= RTE_METRICS_MAX_METRICS) + return -ENOMEM; + + rte_spinlock_lock(&stats->lock); + + /* Overwritten later if this is actually first set.. */ + stats->metadata[stats->idx_last_set].idx_next_set = stats->cnt_stats; + + stats->idx_last_set = idx_base = stats->cnt_stats; + + for (idx_name = 0; idx_name < cnt_names; idx_name++) { + entry = &stats->metadata[idx_name + stats->cnt_stats]; + strncpy(entry->name, names[idx_name], + RTE_METRICS_MAX_NAME_LEN); + memset(entry->value, 0, sizeof(entry->value)); + entry->idx_next_stat = idx_name + stats->cnt_stats + 1; + } + entry->idx_next_stat = 0; + entry->idx_next_set = 0; + stats->cnt_stats += cnt_names; + + rte_spinlock_unlock(&stats->lock); + + return idx_base; +} + +int +rte_metrics_update_value(int port_id, uint16_t key, const uint64_t value) +{ + return rte_metrics_update_values(port_id, key, &value, 1); +} + +int +rte_metrics_update_values(int port_id, + uint16_t key, + const uint64_t *values, + uint32_t count) +{ + struct rte_metrics_meta_s *entry; + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + uint16_t idx_metric; + uint16_t idx_value; + uint16_t cnt_setsize; + + if (port_id != RTE_METRICS_GLOBAL && + (port_id < 0 || port_id > RTE_MAX_ETHPORTS)) + return -EINVAL; + + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); + if (memzone == NULL) + return -EIO; + stats = memzone->addr; + + rte_spinlock_lock(&stats->lock); + idx_metric = key; + cnt_setsize = 1; + while (idx_metric < stats->cnt_stats) { + entry = &stats->metadata[idx_metric]; + if (entry->idx_next_stat == 0) + break; + cnt_setsize++; + idx_metric++; + } + /* Check update does not cross set border */ + if (count > cnt_setsize) { + rte_spinlock_unlock(&stats->lock); + return -ERANGE; + } + + if (port_id == RTE_METRICS_GLOBAL) + for (idx_value = 0; idx_value < count; idx_value++) { + idx_metric = key + idx_value; + stats->metadata[idx_metric].nonport_value = + values[idx_value]; + } + else + for (idx_value = 0; idx_value < count; idx_value++) { + idx_metric = key + idx_value; + stats->metadata[idx_metric].value[port_id] = + values[idx_value]; + } + rte_spinlock_unlock(&stats->lock); + return 0; +} + +int +rte_metrics_get_names(struct rte_metric_name *names, + uint16_t capacity) +{ + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + uint16_t idx_name; + int return_value; + + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); + /* If not allocated, fail silently */ + if (memzone == NULL) + return 0; + + stats = memzone->addr; + rte_spinlock_lock(&stats->lock); + if (names != NULL) { + if (capacity < stats->cnt_stats) { + return_value = stats->cnt_stats; + rte_spinlock_unlock(&stats->lock); + return return_value; + } + for (idx_name = 0; idx_name < stats->cnt_stats; idx_name++) + strncpy(names[idx_name].name, + stats->metadata[idx_name].name, + RTE_METRICS_MAX_NAME_LEN); + } + return_value = stats->cnt_stats; + rte_spinlock_unlock(&stats->lock); + return return_value; +} + +int +rte_metrics_get_values(int port_id, + struct rte_metric_value *values, + uint16_t capacity) +{ + struct rte_metrics_meta_s *entry; + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + uint16_t idx_name; + int return_value; + + if (port_id != RTE_METRICS_GLOBAL && + (port_id < 0 || port_id > RTE_MAX_ETHPORTS)) + return -EINVAL; + + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); + /* If not allocated, fail silently */ + if (memzone == NULL) + return 0; + stats = memzone->addr; + rte_spinlock_lock(&stats->lock); + + if (values != NULL) { + if (capacity < stats->cnt_stats) { + return_value = stats->cnt_stats; + rte_spinlock_unlock(&stats->lock); + return return_value; + } + if (port_id == RTE_METRICS_GLOBAL) + for (idx_name = 0; + idx_name < stats->cnt_stats; + idx_name++) { + entry = &stats->metadata[idx_name]; + values[idx_name].key = idx_name; + values[idx_name].value = entry->nonport_value; + } + else + for (idx_name = 0; + idx_name < stats->cnt_stats; + idx_name++) { + entry = &stats->metadata[idx_name]; + values[idx_name].key = idx_name; + values[idx_name].value = entry->value[port_id]; + } + } + return_value = stats->cnt_stats; + rte_spinlock_unlock(&stats->lock); + return return_value; +} diff --git a/lib/librte_metrics/rte_metrics.h b/lib/librte_metrics/rte_metrics.h new file mode 100644 index 0000000..871a8f9 --- /dev/null +++ b/lib/librte_metrics/rte_metrics.h @@ -0,0 +1,231 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016-2017 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * + * RTE Metrics module + * + * Metric information is populated using a push model, where the + * information provider calls an update function on the relevant + * metrics. Currently only bulk querying of metrics is supported. + */ + +#ifndef _RTE_METRICS_H_ +#define _RTE_METRICS_H_ + +/** Maximum length of metric name (including null-terminator) */ +#define RTE_METRICS_MAX_NAME_LEN 64 + +/** + * Global (rather than port-specific) metric. + * + * When used instead of port number by rte_metrics_update_metric() + * or rte_metrics_update_metric(), the global metrics, which are + * not associated with any specific port, are updated. + */ +#define RTE_METRICS_GLOBAL -1 + + +/** + * A name-key lookup for metrics. + * + * An array of this structure is returned by rte_metrics_get_names(). + * The struct rte_eth_stats references these names via their array index. + */ +struct rte_metric_name { + /** String describing metric */ + char name[RTE_METRICS_MAX_NAME_LEN]; +}; + + +/** + * Metric value structure. + * + * This structure is used by rte_metrics_get_values() to return metrics, + * which are statistics that are not generated by PMDs. It maps a name key, + * which corresponds to an index in the array returned by + * rte_metrics_get_names(). + */ +struct rte_metric_value { + /** Numeric identifier of metric. */ + uint16_t key; + /** Value for metric */ + uint64_t value; +}; + + +/** + * Initializes metric module. This function must be called from + * a primary process before metrics are used. + * + * @param socket_id + * Socket to use for shared memory allocation. + */ +void rte_metrics_init(int socket_id); + +/** + * Register a metric, making it available as a reporting parameter. + * + * Registering a metric is the way third-parties declare a parameter + * that they wish to be reported. Once registered, the associated + * numeric key can be obtained via rte_metrics_get_names(), which + * is required for updating said metric's value. + * + * @param name + * Metric name + * + * @return + * - Zero or positive: Success (index key of new metric) + * - \b -EIO: Error, unable to access metrics shared memory + * (rte_metrics_init() not called) + * - \b -EINVAL: Error, invalid parameters + * - \b -ENOMEM: Error, maximum metrics reached + */ +int rte_metrics_reg_name(const char *name); + +/** + * Register a set of metrics. + * + * This is a bulk version of rte_metrics_reg_metrics() and aside from + * handling multiple keys at once is functionally identical. + * + * @param names + * List of metric names + * + * @param cnt_names + * Number of metrics in set + * + * @return + * - Zero or positive: Success (index key of start of set) + * - \b -EIO: Error, unable to access metrics shared memory + * (rte_metrics_init() not called) + * - \b -EINVAL: Error, invalid parameters + * - \b -ENOMEM: Error, maximum metrics reached + */ +int rte_metrics_reg_names(const char * const *names, uint16_t cnt_names); + +/** + * Get metric name-key lookup table. + * + * @param names + * A struct rte_metric_name array of at least *capacity* in size to + * receive key names. If this is NULL, function returns the required + * number of elements for this array. + * + * @param capacity + * Size (number of elements) of struct rte_metric_name array. + * Disregarded if names is NULL. + * + * @return + * - Positive value above capacity: error, *names* is too small. + * Return value is required size. + * - Positive value equal or less than capacity: Success. Return + * value is number of elements filled in. + * - Negative value: error. + */ +int rte_metrics_get_names( + struct rte_metric_name *names, + uint16_t capacity); + +/** + * Get metric value table. + * + * @param port_id + * Port id to query + * + * @param values + * A struct rte_metric_value array of at least *capacity* in size to + * receive metric ids and values. If this is NULL, function returns + * the required number of elements for this array. + * + * @param capacity + * Size (number of elements) of struct rte_metric_value array. + * Disregarded if names is NULL. + * + * @return + * - Positive value above capacity: error, *values* is too small. + * Return value is required size. + * - Positive value equal or less than capacity: Success. Return + * value is number of elements filled in. + * - Negative value: error. + */ +int rte_metrics_get_values( + int port_id, + struct rte_metric_value *values, + uint16_t capacity); + +/** + * Updates a metric + * + * @param port_id + * Port to update metrics for + * @param key + * Id of metric to update + * @param value + * New value + * + * @return + * - -EIO if unable to access shared metrics memory + * - Zero on success + */ +int rte_metrics_update_value( + int port_id, + uint16_t key, + const uint64_t value); + +/** + * Updates a metric set. Note that it is an error to try to + * update across a set boundary. + * + * @param port_id + * Port to update metrics for + * @param key + * Base id of metrics set to update + * @param values + * Set of new values + * @param count + * Number of new values + * + * @return + * - -ERANGE if count exceeds metric set size + * - -EIO if upable to access shared metrics memory + * - Zero on success + */ +int rte_metrics_update_values( + int port_id, + uint16_t key, + const uint64_t *values, + uint32_t count); + +#endif diff --git a/lib/librte_metrics/rte_metrics_version.map b/lib/librte_metrics/rte_metrics_version.map new file mode 100644 index 0000000..ee28fa0 --- /dev/null +++ b/lib/librte_metrics/rte_metrics_version.map @@ -0,0 +1,13 @@ +DPDK_17.02 { + global: + + rte_metrics_get_names; + rte_metrics_get_values; + rte_metrics_init; + rte_metrics_reg_name; + rte_metrics_reg_names; + rte_metrics_update_value; + rte_metrics_update_values; + + local: *; +}; diff --git a/mk/rte.app.mk b/mk/rte.app.mk index f75f0e2..40fcf33 100644 --- a/mk/rte.app.mk +++ b/mk/rte.app.mk @@ -98,6 +98,8 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_RING) += -lrte_ring _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL) += -lrte_eal _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE) += -lrte_cmdline _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE) += -lrte_cfgfile +_LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS) += -lrte_metrics + _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += -lrte_pmd_bond _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += -lrte_pmd_xenvirt -lxenstore -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [PATCH v9 1/7] lib: add information metrics library 2017-01-18 15:05 ` [dpdk-dev] [PATCH v9 1/7] lib: add information metrics library Remy Horton @ 2017-01-30 15:50 ` Thomas Monjalon 2017-01-30 21:44 ` Remy Horton 2017-01-31 13:13 ` Mcnamara, John 0 siblings, 2 replies; 115+ messages in thread From: Thomas Monjalon @ 2017-01-30 15:50 UTC (permalink / raw) To: Remy Horton; +Cc: dev Hi Remy, > This patch adds a new information metric library that allows other > modules to register named metrics and update their values. It is > intended to be independent of ethdev, rather than mixing ethdev > and non-ethdev information in xstats. I'm still not convinced by this library, and this introduction does not help a lot. I would like to thanks Harry for the review of this series. If we had more opinions or enthousiasm about this patch, it would be easier to accept this new library and assert it is the way to go. It could be a matter of technical board discussion if we had a clear explanation of the needs, the pros and cons of this design. The overview for using this library should be given in the prog guide. 2017-01-18 15:05, Remy Horton: > --- a/config/common_base > +++ b/config/common_base > @@ -593,3 +593,8 @@ CONFIG_RTE_APP_TEST_RESOURCE_TAR=n > CONFIG_RTE_TEST_PMD=y > CONFIG_RTE_TEST_PMD_RECORD_CORE_CYCLES=n > CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n > + > +# > +# Compile the device metrics library > +# > +CONFIG_RTE_LIBRTE_METRICS=y I know the config file is not so well sorted. However it would be a bit more logical below CONFIG_RTE_LIBRTE_JOBSTATS. > diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md > index 72d59b2..94f0f69 100644 > --- a/doc/api/doxy-api-index.md > +++ b/doc/api/doxy-api-index.md > @@ -150,4 +150,5 @@ There are many libraries, so their headers may be grouped by topics: > [common] (@ref rte_common.h), > [ABI compat] (@ref rte_compat.h), > [keepalive] (@ref rte_keepalive.h), > + [Device Metrics] (@ref rte_metrics.h), No first letter uppercase in this list. > --- a/doc/guides/rel_notes/release_17_02.rst > +++ b/doc/guides/rel_notes/release_17_02.rst > @@ -34,6 +34,12 @@ New Features > > Refer to the previous release notes for examples. > > + * **Added information metric library.** > + > + A library that allows information metrics to be added and update. It is update -> updated added and updated by who? > + intended to provide a reporting mechanism that is independent of the > + ethdev library. and independent of the cryptodev library? Does it apply to other types of devices (cryptodev/eventdev)? > + > This section is a comment. do not overwrite or remove it. > Also, make sure to start the actual text at the margin. > ========================================================= Your text should start below this line, and indented at the margin. > @@ -205,6 +211,7 @@ The libraries prepended with a plus sign were incremented in this version. > .. code-block:: diff > > librte_acl.so.2 > + + librte_bitratestats.so.1 not part of this patch > --- a/lib/Makefile > +++ b/lib/Makefile > @@ -58,6 +58,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_TABLE) += librte_table > DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += librte_pipeline > DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder > DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump > +DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics insert it below librte_jobstats is a better choice > --- /dev/null > +++ b/lib/librte_metrics/rte_metrics.c > +/** > + * Internal stats metadata and value entry. > + * > + * @internal > + * @param name > + * Name of metric > + * @param value > + * Current value for metric > + * @param idx_next_set > + * Index of next root element (zero for none) > + * @param idx_next_metric > + * Index of next metric in set (zero for none) > + * > + * Only the root of each set needs idx_next_set but since it has to be > + * assumed that number of sets could equal total number of metrics, > + * having a separate set metadata table doesn't save any memory. > + */ > +struct rte_metrics_meta_s { > + char name[RTE_METRICS_MAX_NAME_LEN]; > + uint64_t value[RTE_MAX_ETHPORTS]; > + uint64_t nonport_value; > + uint16_t idx_next_set; > + uint16_t idx_next_stat; > +}; It would be a lot easier to read with comments near each field. It would avoid to forget some fields like nonport_value in this struct. You do not need to use a doxygen syntax in a .c file. > --- /dev/null > +++ b/lib/librte_metrics/rte_metrics.h > +/** > + * @file > + * > + * RTE Metrics module RTE is not meaningful here. Please prefer DPDK. > + * > + * Metric information is populated using a push model, where the > + * information provider calls an update function on the relevant > + * metrics. Currently only bulk querying of metrics is supported. > + */ This description should explain who is a provider (drivers?) and who is the reader (registered thread?). What do you mean by "push model"? A callback is used? > +/** > + * Global (rather than port-specific) metric. It does not say what kind of constant it is. A special metric id? > + * > + * When used instead of port number by rte_metrics_update_metric() > + * or rte_metrics_update_metric(), the global metrics, which are > + * not associated with any specific port, are updated. > + */ > +#define RTE_METRICS_GLOBAL -1 I thought you agreed that "port" is not really a good wording. > +/** > + * A name-key lookup for metrics. > + * > + * An array of this structure is returned by rte_metrics_get_names(). > + * The struct rte_eth_stats references these names via their array index. rte_eth_stats? > + */ > +struct rte_metric_name { > + /** String describing metric */ > + char name[RTE_METRICS_MAX_NAME_LEN]; > +}; [...] > +/** > + * Metric value structure. > + * > + * This structure is used by rte_metrics_get_values() to return metrics, > + * which are statistics that are not generated by PMDs. It maps a name key, Here we have a definition of what is a metric: "statistics that are not generated by PMDs" It could help in the introduction. > + * which corresponds to an index in the array returned by > + * rte_metrics_get_names(). > + */ > +struct rte_metric_value { > + /** Numeric identifier of metric. */ > + uint16_t key; > + /** Value for metric */ > + uint64_t value; > +}; > + > + > +/** > + * Initializes metric module. This function must be called from > + * a primary process before metrics are used. Why not integrating it in the global init? Is there some performance drawbacks? > + * > + * @param socket_id > + * Socket to use for shared memory allocation. > + */ > +void rte_metrics_init(int socket_id); > + > +/** > + * Register a metric, making it available as a reporting parameter. > + * > + * Registering a metric is the way third-parties declare a parameter third-party? You mean the provider? > + * that they wish to be reported. Once registered, the associated > + * numeric key can be obtained via rte_metrics_get_names(), which > + * is required for updating said metric's value. > + * > + * @param name > + * Metric name > + * > + * @return > + * - Zero or positive: Success (index key of new metric) > + * - \b -EIO: Error, unable to access metrics shared memory > + * (rte_metrics_init() not called) > + * - \b -EINVAL: Error, invalid parameters > + * - \b -ENOMEM: Error, maximum metrics reached Please, no extra formatting in doxygen. > + */ > +int rte_metrics_reg_name(const char *name); > + ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [PATCH v9 1/7] lib: add information metrics library 2017-01-30 15:50 ` Thomas Monjalon @ 2017-01-30 21:44 ` Remy Horton 2017-01-31 13:13 ` Mcnamara, John 1 sibling, 0 replies; 115+ messages in thread From: Remy Horton @ 2017-01-30 21:44 UTC (permalink / raw) To: Thomas Monjalon; +Cc: dev Some points addressed. Will cover other ones later. On 30/01/2017 15:50, Thomas Monjalon wrote: [..] >> +CONFIG_RTE_LIBRTE_METRICS=y > I know the config file is not so well sorted. > However it would be a bit more logical below CONFIG_RTE_LIBRTE_JOBSTATS. Done. Rebase merging doesn't help with sorting here. >> + [Device Metrics] (@ref rte_metrics.h), > No first letter uppercase in this list. Fixed. >> + A library that allows information metrics to be added and update. It is > update -> updated Fixed. > added and updated by who? Elaborated. >> + intended to provide a reporting mechanism that is independent of the >> + ethdev library. > and independent of the cryptodev library? Yes. The aim is to have no sub-dependencies. My original plan was to introduce some form of parameter registration scheme into xstats to replace the current hard-coded tables, since I suspected libbitrate/liblatency would not be the last additions. I decided to spin it out into a library in its own right, as it seemed cleaner than shoving a load of non-driver stuff into xstats. > Does it apply to other types of devices (cryptodev/eventdev)? I've not been following cryptodev/eventdev, but short answer yes. >> This section is a comment. do not overwrite or remove it. >> Also, make sure to start the actual text at the margin. >> ========================================================= > Your text should start below this line, and indented at the margin. Fixed. >> + + librte_bitratestats.so.1 > not part of this patch Fixed. Artefact of sorting out a merge mess-up. >> +DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics > insert it below librte_jobstats is a better choice Done. >> +struct rte_metrics_meta_s { >> + char name[RTE_METRICS_MAX_NAME_LEN]; >> + uint64_t value[RTE_MAX_ETHPORTS]; >> + uint64_t nonport_value; >> + uint16_t idx_next_set; >> + uint16_t idx_next_stat; >> +}; > It would be a lot easier to read with comments near each field. > It would avoid to forget some fields like nonport_value in this struct. > You do not need to use a doxygen syntax in a .c file. Noted. Even though Doxygen isn't required, I think it preferable to use a consistent style in both .c and .h files. >> + * RTE Metrics module > RTE is not meaningful here. > Please prefer DPDK. Fixed. >> + * Metric information is populated using a push model, where the >> + * information provider calls an update function on the relevant >> + * metrics. Currently only bulk querying of metrics is supported. >> + */ > This description should explain who is a provider (drivers?) and who > is the reader (registered thread?). Noted. Will elaborate. > What do you mean by "push model"? A callback is used? Updating is done in response to producers having new information. In contrast in a pull model an update would happen in response to a polling by a consumer. Originally (back in August I think) I used a pull model where producers would register callbacks that were called in response to rte_metrics_get() by a consumer, but that assumed that producers and consumers were within the same process. Using shared memory and making it ASLR-safe means not using pointers. Aside: In this former pull model, port_id was passed verbatim to the producers' callbacks to interpret in whatever way they saw fit, so there was no inherant need to stop "magic" values outside the usual 0-255 used for port ids. Hence where the next thing originally came from... >> +/** >> + * Global (rather than port-specific) metric. > It does not say what kind of constant it is. A special metric id? Yes. Elaborated. >> + * >> + * When used instead of port number by rte_metrics_update_metric() >> + * or rte_metrics_update_metric(), the global metrics, which are >> + * not associated with any specific port, are updated. >> + */ >> +#define RTE_METRICS_GLOBAL -1 > > I thought you agreed that "port" is not really a good wording. Certainly within the constant name. Don't see what's wrong with referring to it in description though. >> + * An array of this structure is returned by rte_metrics_get_names(). >> + * The struct rte_eth_stats references these names via their array index. > rte_eth_stats? Good question - was going to put it down to cut'n'paste while baseing the descriptions on Olivier Matz's rewording, but that was for xstats.. >> + * Initializes metric module. This function must be called from >> + * a primary process before metrics are used. > > Why not integrating it in the global init? > Is there some performance drawbacks? There shouldn't be any significant performance penalities, but I am not particularly fond in principle of initalising component libraries regardless of whether they are used. (Actually it was previously initalised on first use, but that had a race condition.) >> + * Registering a metric is the way third-parties declare a parameter > third-party? You mean the provider? Yes. >> + * - \b -EINVAL: Error, invalid parameters >> + * - \b -ENOMEM: Error, maximum metrics reached > Please, no extra formatting in doxygen. Fixed. ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [PATCH v9 1/7] lib: add information metrics library 2017-01-30 15:50 ` Thomas Monjalon 2017-01-30 21:44 ` Remy Horton @ 2017-01-31 13:13 ` Mcnamara, John 2017-01-31 13:28 ` Bruce Richardson 1 sibling, 1 reply; 115+ messages in thread From: Mcnamara, John @ 2017-01-31 13:13 UTC (permalink / raw) To: Thomas Monjalon, Horton, Remy; +Cc: dev > -----Original Message----- > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Thomas Monjalon > Sent: Monday, January 30, 2017 3:50 PM > To: Horton, Remy <remy.horton@intel.com> > Cc: dev@dpdk.org > Subject: Re: [dpdk-dev] [PATCH v9 1/7] lib: add information metrics > library > > Hi Remy, > > > This patch adds a new information metric library that allows other > > modules to register named metrics and update their values. It is > > intended to be independent of ethdev, rather than mixing ethdev and > > non-ethdev information in xstats. > > I'm still not convinced by this library, and this introduction does not > help a lot. > > I would like to thanks Harry for the review of this series. > If we had more opinions or enthousiasm about this patch, it would be > easier to accept this new library and assert it is the way to go. Hi, The RFCs for this library (initially two, merged into one) have been up since October, during the 16.11 timeframe. Comments were made and applied. http://dpdk.org/ml/archives/dev/2016-October/049571.html http://dpdk.org/ml/archives/dev/2016-October/048390.html I'm concerned that these new comments/reservations are coming in very, very late in the 17.02 release cycle. If there hasn't been a lot of opinions or enthusiasm then equally there hasn't been other reservations. If there had been we would have addressed them. > It could be a matter of technical board discussion if we had a clear > explanation of the needs, the pros and cons of this design. We are happy to have the design discussed at the Technical Board. We would also like the inclusion of this library in RC3 to be discussed since that is still our desired outcome. We have, as any other company would have, customers awaiting features, developers committed to timelines, and testing and integration roadmaps. Blocking or delaying features at the last moment isn't an effective model that we, and I'm sure other companies, can work with. As such, it is probably best, that all current and future RFCs are reviewed at the Technical Board and that the board gives an indication on whether the proposal is acceptable for upstreaming or not. > The overview for using this library should be given in the prog guide. We will add a section to the Programmers Guide. John ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [PATCH v9 1/7] lib: add information metrics library 2017-01-31 13:13 ` Mcnamara, John @ 2017-01-31 13:28 ` Bruce Richardson 2017-02-02 17:22 ` Thomas Monjalon 0 siblings, 1 reply; 115+ messages in thread From: Bruce Richardson @ 2017-01-31 13:28 UTC (permalink / raw) To: Mcnamara, John; +Cc: Thomas Monjalon, Horton, Remy, dev On Tue, Jan 31, 2017 at 01:13:11PM +0000, Mcnamara, John wrote: > > > > -----Original Message----- > > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Thomas Monjalon > > Sent: Monday, January 30, 2017 3:50 PM > > To: Horton, Remy <remy.horton@intel.com> > > Cc: dev@dpdk.org > > Subject: Re: [dpdk-dev] [PATCH v9 1/7] lib: add information metrics > > library > > > > Hi Remy, > > > > > This patch adds a new information metric library that allows other > > > modules to register named metrics and update their values. It is > > > intended to be independent of ethdev, rather than mixing ethdev and > > > non-ethdev information in xstats. > > > > I'm still not convinced by this library, and this introduction does not > > help a lot. > > > > I would like to thanks Harry for the review of this series. > > If we had more opinions or enthousiasm about this patch, it would be > > easier to accept this new library and assert it is the way to go. > > Hi, > > The RFCs for this library (initially two, merged into one) have been up since October, during the 16.11 timeframe. Comments were made and applied. > > http://dpdk.org/ml/archives/dev/2016-October/049571.html > http://dpdk.org/ml/archives/dev/2016-October/048390.html > > I'm concerned that these new comments/reservations are coming in very, very late in the 17.02 release cycle. > > If there hasn't been a lot of opinions or enthusiasm then equally there hasn't been other reservations. If there had been we would have addressed them. > > > > It could be a matter of technical board discussion if we had a clear > > explanation of the needs, the pros and cons of this design. > > We are happy to have the design discussed at the Technical Board. We would also like the inclusion of this library in RC3 to be discussed since that is still our desired outcome. > > We have, as any other company would have, customers awaiting features, developers committed to timelines, and testing and integration roadmaps. Blocking or delaying features at the last moment isn't an effective model that we, and I'm sure other companies, can work with. > > As such, it is probably best, that all current and future RFCs are reviewed at the Technical Board and that the board gives an indication on whether the proposal is acceptable for upstreaming or not. > I would tend to agree with this. The tech board should indeed look to insure that all RFCs and V1s have had some feedback on them well before the merge deadline. I don't believe it's fair on developers to suddenly give feedback at merge-time and thereby prevent the patch making it into a release, without giving time to do any rework. This is especially true if the patch had already been reviewed and acked, and so could be considered "ready for merge". The tech board should also discuss some reasonable guidelines for this area. My opinion is that by the time RC1 is released, any patches that have been reviewed, acked and have no outstanding comments on them for e.g. 1 week, must be merged in for the release. Any additional feedback thereafter should be considered "too late", and should be addressed in the following release. This will help to incentivize reviewers to review early, and also give developers some degree of confidence that their patches will be merged in. We have deadlines for submitters to get patches in, we should also have deadlines for reviewers to object to those patches. Regards, /Bruce ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [PATCH v9 1/7] lib: add information metrics library 2017-01-31 13:28 ` Bruce Richardson @ 2017-02-02 17:22 ` Thomas Monjalon 0 siblings, 0 replies; 115+ messages in thread From: Thomas Monjalon @ 2017-02-02 17:22 UTC (permalink / raw) To: Bruce Richardson, Mcnamara, John, Horton, Remy; +Cc: dev 2017-01-31 13:28, Bruce Richardson: > On Tue, Jan 31, 2017 at 01:13:11PM +0000, Mcnamara, John wrote: > > From: Thomas Monjalon > > > Hi Remy, > > > > > > > This patch adds a new information metric library that allows other > > > > modules to register named metrics and update their values. It is > > > > intended to be independent of ethdev, rather than mixing ethdev and > > > > non-ethdev information in xstats. > > > > > > I'm still not convinced by this library, and this introduction does not > > > help a lot. > > > > > > I would like to thanks Harry for the review of this series. > > > If we had more opinions or enthousiasm about this patch, it would be > > > easier to accept this new library and assert it is the way to go. > > > > Hi, > > > > The RFCs for this library (initially two, merged into one) have been up since October, during the 16.11 timeframe. Comments were made and applied. > > > > http://dpdk.org/ml/archives/dev/2016-October/049571.html > > http://dpdk.org/ml/archives/dev/2016-October/048390.html > > > > I'm concerned that these new comments/reservations are coming in very, very late in the 17.02 release cycle. > > > > If there hasn't been a lot of opinions or enthusiasm then equally there hasn't been other reservations. If there had been we would have addressed them. > > > > > > > It could be a matter of technical board discussion if we had a clear > > > explanation of the needs, the pros and cons of this design. > > > > We are happy to have the design discussed at the Technical Board. We would also like the inclusion of this library in RC3 to be discussed since that is still our desired outcome. > > > > We have, as any other company would have, customers awaiting features, developers committed to timelines, and testing and integration roadmaps. Blocking or delaying features at the last moment isn't an effective model that we, and I'm sure other companies, can work with. > > > > As such, it is probably best, that all current and future RFCs are reviewed at the Technical Board and that the board gives an indication on whether the proposal is acceptable for upstreaming or not. > > > > I would tend to agree with this. The tech board should indeed look to > insure that all RFCs and V1s have had some feedback on them well before > the merge deadline. > > I don't believe it's fair on developers to suddenly give feedback at > merge-time and thereby prevent the patch making it into a release, > without giving time to do any rework. This is especially true if the > patch had already been reviewed and acked, and so could be considered > "ready for merge". > > The tech board should also discuss some reasonable guidelines > for this area. My opinion is that by the time RC1 is released, any > patches that have been reviewed, acked and have no outstanding > comments on them for e.g. 1 week, must be merged in for the release. Any > additional feedback thereafter should be considered "too late", and > should be addressed in the following release. This will help to > incentivize reviewers to review early, and also give developers some > degree of confidence that their patches will be merged in. We have > deadlines for submitters to get patches in, we should also have > deadlines for reviewers to object to those patches. We are talking about adding some new libraries in DPDK. I think it is a special case where the submitter should make sure other contributors agree to add such new capabilities in DPDK. Saying there are some customers waiting for this feature to be upstreamed is not a good argument. But it could help to explain what the goal of this series. I agree this kind of comment should happen earlier and I'm sorry to not have explicit them in earlier stages. That's why I suggest the Technical Board could monitor this kind of proposal and make sure the discussion is progressing. ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v9 2/7] app/proc_info: add metrics displaying 2017-01-18 15:05 ` [dpdk-dev] [PATCH v9 0/7] Expanded statistics reporting Remy Horton 2017-01-18 15:05 ` [dpdk-dev] [PATCH v9 1/7] lib: add information metrics library Remy Horton @ 2017-01-18 15:05 ` Remy Horton 2017-01-18 15:05 ` [dpdk-dev] [PATCH v9 3/7] lib: add bitrate statistics library Remy Horton ` (5 subsequent siblings) 7 siblings, 0 replies; 115+ messages in thread From: Remy Horton @ 2017-01-18 15:05 UTC (permalink / raw) To: dev; +Cc: Reshma Pattan, Thomas Monjalon From: Reshma Pattan <reshma.pattan@intel.com> Modify the dpdk-procinfo process to display the newly added metrics. Added new command line option "--metrics" to display metrics. Signed-off-by: Reshma Pattan <reshma.pattan@intel.com> Signed-off-by: Remy Horton <remy.horton@intel.com> --- app/proc_info/main.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 78 insertions(+), 1 deletion(-) diff --git a/app/proc_info/main.c b/app/proc_info/main.c index 2c56d10..f513669 100644 --- a/app/proc_info/main.c +++ b/app/proc_info/main.c @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2010-2016 Intel Corporation. All rights reserved. + * Copyright(c) 2010-2017 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -57,6 +57,7 @@ #include <rte_atomic.h> #include <rte_branch_prediction.h> #include <rte_string_fns.h> +#include <rte_metrics.h> /* Maximum long option length for option parsing. */ #define MAX_LONG_OPT_SZ 64 @@ -68,6 +69,8 @@ static uint32_t enabled_port_mask; static uint32_t enable_stats; /**< Enable xstats. */ static uint32_t enable_xstats; +/**< Enable metrics. */ +static uint32_t enable_metrics; /**< Enable stats reset. */ static uint32_t reset_stats; /**< Enable xstats reset. */ @@ -85,6 +88,8 @@ proc_info_usage(const char *prgname) " --stats: to display port statistics, enabled by default\n" " --xstats: to display extended port statistics, disabled by " "default\n" + " --metrics: to display derived metrics of the ports, disabled by " + "default\n" " --stats-reset: to reset port statistics\n" " --xstats-reset: to reset port extended statistics\n", prgname); @@ -127,6 +132,7 @@ proc_info_parse_args(int argc, char **argv) {"stats", 0, NULL, 0}, {"stats-reset", 0, NULL, 0}, {"xstats", 0, NULL, 0}, + {"metrics", 0, NULL, 0}, {"xstats-reset", 0, NULL, 0}, {NULL, 0, 0, 0} }; @@ -159,6 +165,10 @@ proc_info_parse_args(int argc, char **argv) else if (!strncmp(long_option[option_index].name, "xstats", MAX_LONG_OPT_SZ)) enable_xstats = 1; + else if (!strncmp(long_option[option_index].name, + "metrics", + MAX_LONG_OPT_SZ)) + enable_metrics = 1; /* Reset stats */ if (!strncmp(long_option[option_index].name, "stats-reset", MAX_LONG_OPT_SZ)) @@ -301,6 +311,67 @@ nic_xstats_clear(uint8_t port_id) printf("\n NIC extended statistics for port %d cleared\n", port_id); } +static void +metrics_display(int port_id) +{ + struct rte_metric_value *metrics; + struct rte_metric_name *names; + int len, ret; + static const char *nic_stats_border = "########################"; + + len = rte_metrics_get_names(NULL, 0); + if (len < 0) { + printf("Cannot get metrics count\n"); + return; + } + if (len == 0) { + printf("No metrics to display (none have been registered)\n"); + return; + } + + metrics = rte_malloc("proc_info_metrics", + sizeof(struct rte_metric_value) * len, 0); + if (metrics == NULL) { + printf("Cannot allocate memory for metrics\n"); + return; + } + + names = rte_malloc(NULL, sizeof(struct rte_metric_name) * len, 0); + if (names == NULL) { + printf("Cannot allocate memory for metrcis names\n"); + rte_free(metrics); + return; + } + + if (len != rte_metrics_get_names(names, len)) { + printf("Cannot get metrics names\n"); + rte_free(metrics); + rte_free(names); + return; + } + + if (port_id == RTE_METRICS_GLOBAL) + printf("###### Non port specific metrics #########\n"); + else + printf("###### metrics for port %-2d #########\n", port_id); + printf("%s############################\n", nic_stats_border); + ret = rte_metrics_get_values(port_id, metrics, len); + if (ret < 0 || ret > len) { + printf("Cannot get metrics values\n"); + rte_free(metrics); + rte_free(names); + return; + } + + int i; + for (i = 0; i < len; i++) + printf("%s: %"PRIu64"\n", names[i].name, metrics[i].value); + + printf("%s############################\n", nic_stats_border); + rte_free(metrics); + rte_free(names); +} + int main(int argc, char **argv) { @@ -360,8 +431,14 @@ main(int argc, char **argv) nic_stats_clear(i); else if (reset_xstats) nic_xstats_clear(i); + else if (enable_metrics) + metrics_display(i); } } + /* print port independent stats */ + if (enable_metrics) + metrics_display(RTE_METRICS_GLOBAL); + return 0; } -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v9 3/7] lib: add bitrate statistics library 2017-01-18 15:05 ` [dpdk-dev] [PATCH v9 0/7] Expanded statistics reporting Remy Horton 2017-01-18 15:05 ` [dpdk-dev] [PATCH v9 1/7] lib: add information metrics library Remy Horton 2017-01-18 15:05 ` [dpdk-dev] [PATCH v9 2/7] app/proc_info: add metrics displaying Remy Horton @ 2017-01-18 15:05 ` Remy Horton 2017-01-18 15:05 ` [dpdk-dev] [PATCH v9 4/7] app/test-pmd: add bitrate statistics calculation Remy Horton ` (4 subsequent siblings) 7 siblings, 0 replies; 115+ messages in thread From: Remy Horton @ 2017-01-18 15:05 UTC (permalink / raw) To: dev; +Cc: Thomas Monjalon This patch adds a library that calculates peak and average data-rate statistics. For ethernet devices. These statistics are reported using the metrics library. Signed-off-by: Remy Horton <remy.horton@intel.com> --- MAINTAINERS | 4 + config/common_base | 5 + doc/api/doxy-api-index.md | 1 + doc/api/doxy-api.conf | 1 + doc/guides/rel_notes/release_17_02.rst | 5 + lib/Makefile | 1 + lib/librte_bitratestats/Makefile | 53 +++++++++ lib/librte_bitratestats/rte_bitrate.c | 132 +++++++++++++++++++++ lib/librte_bitratestats/rte_bitrate.h | 80 +++++++++++++ .../rte_bitratestats_version.map | 9 ++ mk/rte.app.mk | 1 + 11 files changed, 292 insertions(+) create mode 100644 lib/librte_bitratestats/Makefile create mode 100644 lib/librte_bitratestats/rte_bitrate.c create mode 100644 lib/librte_bitratestats/rte_bitrate.h create mode 100644 lib/librte_bitratestats/rte_bitratestats_version.map diff --git a/MAINTAINERS b/MAINTAINERS index 95836a2..d9423cb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -600,6 +600,10 @@ Metrics M: Remy Horton <remy.horton@intel.com> F: lib/librte_metrics/ +Bit-rate statistica +M: Remy Horton <remy.horton@intel.com> +F: lib/librte_bitratestats/ + Test Applications ----------------- diff --git a/config/common_base b/config/common_base index 0eb3866..decebe5 100644 --- a/config/common_base +++ b/config/common_base @@ -598,3 +598,8 @@ CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n # Compile the device metrics library # CONFIG_RTE_LIBRTE_METRICS=y + +# +# Compile the bitrate statistics library +# +CONFIG_RTE_LIBRTE_BITRATE=y diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md index 94f0f69..5e194b0 100644 --- a/doc/api/doxy-api-index.md +++ b/doc/api/doxy-api-index.md @@ -151,4 +151,5 @@ There are many libraries, so their headers may be grouped by topics: [ABI compat] (@ref rte_compat.h), [keepalive] (@ref rte_keepalive.h), [Device Metrics] (@ref rte_metrics.h), + [Bitrate Statistics] (@ref rte_bitrate.h), [version] (@ref rte_version.h) diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf index 194b670..6e6ab5c 100644 --- a/doc/api/doxy-api.conf +++ b/doc/api/doxy-api.conf @@ -35,6 +35,7 @@ INPUT = doc/api/doxy-api-index.md \ lib/librte_eal/common/include \ lib/librte_eal/common/include/generic \ lib/librte_acl \ + lib/librte_bitratestats \ lib/librte_cfgfile \ lib/librte_cmdline \ lib/librte_compat \ diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst index abbfe4a..421270c 100644 --- a/doc/guides/rel_notes/release_17_02.rst +++ b/doc/guides/rel_notes/release_17_02.rst @@ -40,6 +40,11 @@ New Features intended to provide a reporting mechanism that is independent of the ethdev library. + * **Added bit-rate calculation library.** + + A library that can be used to calculate device bit-rates. Calculated + bitrates are reported using the metrics library. + This section is a comment. do not overwrite or remove it. Also, make sure to start the actual text at the margin. ========================================================= diff --git a/lib/Makefile b/lib/Makefile index 5d85dcf..e211bc0 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -59,6 +59,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_PIPELINE) += librte_pipeline DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics +DIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += librte_bitratestats ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni diff --git a/lib/librte_bitratestats/Makefile b/lib/librte_bitratestats/Makefile new file mode 100644 index 0000000..743b62c --- /dev/null +++ b/lib/librte_bitratestats/Makefile @@ -0,0 +1,53 @@ +# BSD LICENSE +# +# Copyright(c) 2016-2017 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +include $(RTE_SDK)/mk/rte.vars.mk + +# library name +LIB = librte_bitratestats.a + +CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) + +EXPORT_MAP := rte_bitratestats_version.map + +LIBABIVER := 1 + +# all source are stored in SRCS-y +SRCS-$(CONFIG_RTE_LIBRTE_BITRATE) := rte_bitrate.c + +# Install header file +SYMLINK-$(CONFIG_RTE_LIBRTE_BITRATE)-include += rte_bitrate.h + +DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_eal +DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_ether +DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_metrics + +include $(RTE_SDK)/mk/rte.lib.mk diff --git a/lib/librte_bitratestats/rte_bitrate.c b/lib/librte_bitratestats/rte_bitrate.c new file mode 100644 index 0000000..2c20272 --- /dev/null +++ b/lib/librte_bitratestats/rte_bitrate.c @@ -0,0 +1,132 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016-2017 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <rte_common.h> +#include <rte_ethdev.h> +#include <rte_malloc.h> +#include <rte_metrics.h> +#include <rte_bitrate.h> + +/* + * Persistent bit-rate data. + * @internal + */ +struct rte_stats_bitrate { + uint64_t last_ibytes; + uint64_t last_obytes; + uint64_t peak_ibits; + uint64_t peak_obits; + uint64_t ewma_ibits; + uint64_t ewma_obits; +}; + +struct rte_stats_bitrates { + struct rte_stats_bitrate port_stats[RTE_MAX_ETHPORTS]; + uint16_t id_stats_set; +}; + +struct rte_stats_bitrates * +rte_stats_bitrate_create(void) +{ + return rte_zmalloc(NULL, sizeof(struct rte_stats_bitrates), + RTE_CACHE_LINE_SIZE); +} + +int +rte_stats_bitrate_reg(struct rte_stats_bitrates *bitrate_data) +{ + const char * const names[] = { + "mean_bits_in", "mean_bits_out", + "peak_bits_in", "peak_bits_out", + }; + int return_value; + + return_value = rte_metrics_reg_names(&names[0], 4); + if (return_value >= 0) + bitrate_data->id_stats_set = return_value; + return return_value; +} + +int +rte_stats_bitrate_calc(struct rte_stats_bitrates *bitrate_data, + uint8_t port_id) +{ + struct rte_stats_bitrate *port_data; + struct rte_eth_stats eth_stats; + int ret_code; + uint64_t cnt_bits; + int64_t delta; + const int64_t alpha_percent = 20; + uint64_t values[4]; + + ret_code = rte_eth_stats_get(port_id, ð_stats); + if (ret_code != 0) + return ret_code; + + port_data = &bitrate_data->port_stats[port_id]; + + /* Incoming bitrate. This is an iteratively calculated EWMA + * (Expomentially Weighted Moving Average) that uses a + * weighting factor of alpha_percent. + */ + cnt_bits = (eth_stats.ibytes - port_data->last_ibytes) << 3; + port_data->last_ibytes = eth_stats.ibytes; + if (cnt_bits > port_data->peak_ibits) + port_data->peak_ibits = cnt_bits; + delta = cnt_bits; + delta -= port_data->ewma_ibits; + /* The +-50 fixes integer rounding during divison */ + if (delta > 0) + delta = (delta * alpha_percent + 50) / 100; + else + delta = (delta * alpha_percent - 50) / 100; + port_data->ewma_ibits += delta; + + /* Outgoing bitrate (also EWMA) */ + cnt_bits = (eth_stats.obytes - port_data->last_obytes) << 3; + port_data->last_obytes = eth_stats.obytes; + if (cnt_bits > port_data->peak_obits) + port_data->peak_obits = cnt_bits; + delta = cnt_bits; + delta -= port_data->ewma_obits; + delta = (delta * alpha_percent + 50) / 100; + port_data->ewma_obits += delta; + + values[0] = port_data->ewma_ibits; + values[1] = port_data->ewma_obits; + values[2] = port_data->peak_ibits; + values[3] = port_data->peak_obits; + rte_metrics_update_values(port_id, bitrate_data->id_stats_set, + values, 4); + return 0; +} diff --git a/lib/librte_bitratestats/rte_bitrate.h b/lib/librte_bitratestats/rte_bitrate.h new file mode 100644 index 0000000..564e4f7 --- /dev/null +++ b/lib/librte_bitratestats/rte_bitrate.h @@ -0,0 +1,80 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016-2017 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +/** + * Bitrate statistics data structure. + * This data structure is intentionally opaque. + */ +struct rte_stats_bitrates; + + +/** + * Allocate a bitrate statistics structure + * + * @return + * - Pointer to structure on success + * - NULL on error (zmalloc failure) + */ +struct rte_stats_bitrates *rte_stats_bitrate_create(void); + + +/** + * Register bitrate statistics with the metric library. + * + * @param bitrate_data + * Pointer allocated by rte_stats_create() + * + * @return + * Zero on success + * Negative on error + */ +int rte_stats_bitrate_reg(struct rte_stats_bitrates *bitrate_data); + + +/** + * Calculate statistics for current time window. The period with which + * this function is called should be the intended sampling window width. + * + * @param bitrate_data + * Bitrate statistics data pointer + * + * @param port_id + * Port id to calculate statistics for + * + * @return + * - Zero on success + * - Negative value on error + */ +int rte_stats_bitrate_calc(struct rte_stats_bitrates *bitrate_data, + uint8_t port_id); diff --git a/lib/librte_bitratestats/rte_bitratestats_version.map b/lib/librte_bitratestats/rte_bitratestats_version.map new file mode 100644 index 0000000..66f232f --- /dev/null +++ b/lib/librte_bitratestats/rte_bitratestats_version.map @@ -0,0 +1,9 @@ +DPDK_17.02 { + global: + + rte_stats_bitrate_calc; + rte_stats_bitrate_create; + rte_stats_bitrate_reg; + + local: *; +}; diff --git a/mk/rte.app.mk b/mk/rte.app.mk index 40fcf33..6aac5ac 100644 --- a/mk/rte.app.mk +++ b/mk/rte.app.mk @@ -99,6 +99,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL) += -lrte_eal _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE) += -lrte_cmdline _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE) += -lrte_cfgfile _LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS) += -lrte_metrics +_LDLIBS-$(CONFIG_RTE_LIBRTE_BITRATE) += -lrte_bitratestats _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += -lrte_pmd_bond -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v9 4/7] app/test-pmd: add bitrate statistics calculation 2017-01-18 15:05 ` [dpdk-dev] [PATCH v9 0/7] Expanded statistics reporting Remy Horton ` (2 preceding siblings ...) 2017-01-18 15:05 ` [dpdk-dev] [PATCH v9 3/7] lib: add bitrate statistics library Remy Horton @ 2017-01-18 15:05 ` Remy Horton 2017-01-18 15:05 ` [dpdk-dev] [PATCH v9 5/7] mbuf: add a timestamp to the mbuf for latencystats Remy Horton ` (3 subsequent siblings) 7 siblings, 0 replies; 115+ messages in thread From: Remy Horton @ 2017-01-18 15:05 UTC (permalink / raw) To: dev; +Cc: Thomas Monjalon Calculate bitrate statistics using the bitrate stats library. The resulting statistics can be viewed via proc_info. Signed-off-by: Remy Horton <remy.horton@intel.com> --- app/test-pmd/testpmd.c | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c index bfb2f8e..b31a300 100644 --- a/app/test-pmd/testpmd.c +++ b/app/test-pmd/testpmd.c @@ -1,7 +1,7 @@ /*- * BSD LICENSE * - * Copyright(c) 2010-2016 Intel Corporation. All rights reserved. + * Copyright(c) 2010-2017 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -79,6 +79,10 @@ #include <rte_pdump.h> #endif #include <rte_flow.h> +#include <rte_metrics.h> +#ifdef RTE_LIBRTE_BITRATE +#include <rte_bitrate.h> +#endif #include "testpmd.h" @@ -323,6 +327,9 @@ uint16_t nb_rx_queue_stats_mappings = 0; unsigned max_socket = 0; +/* Bitrate statistics */ +struct rte_stats_bitrates *bitrate_data; + /* Forward function declarations */ static void map_port_queue_stats_mapping_registers(uint8_t pi, struct rte_port *port); static void check_all_ports_link_status(uint32_t port_mask); @@ -922,12 +929,32 @@ run_pkt_fwd_on_lcore(struct fwd_lcore *fc, packet_fwd_t pkt_fwd) struct fwd_stream **fsm; streamid_t nb_fs; streamid_t sm_id; +#ifdef RTE_LIBRTE_BITRATE + uint64_t tics_per_1sec; + uint64_t tics_datum; + uint64_t tics_current; + uint8_t idx_port, cnt_ports; +#endif +#ifdef RTE_LIBRTE_BITRATE + cnt_ports = rte_eth_dev_count(); + tics_datum = rte_rdtsc(); + tics_per_1sec = rte_get_timer_hz(); +#endif fsm = &fwd_streams[fc->stream_idx]; nb_fs = fc->stream_nb; do { for (sm_id = 0; sm_id < nb_fs; sm_id++) (*pkt_fwd)(fsm[sm_id]); +#ifdef RTE_LIBRTE_BITRATE + tics_current = rte_rdtsc(); + if (tics_current - tics_datum >= tics_per_1sec) { + /* Periodic bitrate calculation */ + for (idx_port = 0; idx_port < cnt_ports; idx_port++) + rte_stats_bitrate_calc(bitrate_data, idx_port); + tics_datum = tics_current; + } +#endif } while (! fc->stopped); } @@ -2139,6 +2166,18 @@ main(int argc, char** argv) FOREACH_PORT(port_id, ports) rte_eth_promiscuous_enable(port_id); + /* Init metrics library */ + rte_metrics_init(rte_socket_id()); + + /* Setup bitrate stats */ +#ifdef RTE_LIBRTE_BITRATE + bitrate_data = rte_stats_bitrate_create(); + if (bitrate_data == NULL) + rte_exit(EXIT_FAILURE, "Could not allocate bitrate data.\n"); + rte_stats_bitrate_reg(bitrate_data); +#endif + + #ifdef RTE_LIBRTE_CMDLINE if (interactive == 1) { if (auto_start) { -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v9 5/7] mbuf: add a timestamp to the mbuf for latencystats 2017-01-18 15:05 ` [dpdk-dev] [PATCH v9 0/7] Expanded statistics reporting Remy Horton ` (3 preceding siblings ...) 2017-01-18 15:05 ` [dpdk-dev] [PATCH v9 4/7] app/test-pmd: add bitrate statistics calculation Remy Horton @ 2017-01-18 15:05 ` Remy Horton 2017-01-18 15:05 ` [dpdk-dev] [PATCH v9 6/7] lib: added new library for latency stats Remy Horton ` (2 subsequent siblings) 7 siblings, 0 replies; 115+ messages in thread From: Remy Horton @ 2017-01-18 15:05 UTC (permalink / raw) To: dev; +Cc: Harry van Haaren, Thomas Monjalon, Reshma Pattan From: Harry van Haaren <harry.van.haaren@intel.com> This commit adds a uint64_t to the mbuf struct, allowing collection of latency and jitter statistics by measuring packet I/O timestamps. This change is required by the latencystats library. Signed-off-by: Reshma Pattan <reshma.pattan@intel.com> Signed-off-by: Harry van Haaren <harry.van.haaren@intel.com> --- lib/librte_mbuf/rte_mbuf.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h index bfce9f4..c35ba0a 100644 --- a/lib/librte_mbuf/rte_mbuf.h +++ b/lib/librte_mbuf/rte_mbuf.h @@ -512,6 +512,9 @@ struct rte_mbuf { /** Timesync flags for use with IEEE1588. */ uint16_t timesync; + + /** Timestamp for measuring latency. */ + uint64_t timestamp; } __rte_cache_aligned; /** -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v9 6/7] lib: added new library for latency stats 2017-01-18 15:05 ` [dpdk-dev] [PATCH v9 0/7] Expanded statistics reporting Remy Horton ` (4 preceding siblings ...) 2017-01-18 15:05 ` [dpdk-dev] [PATCH v9 5/7] mbuf: add a timestamp to the mbuf for latencystats Remy Horton @ 2017-01-18 15:05 ` Remy Horton 2017-01-18 15:05 ` [dpdk-dev] [PATCH v9 7/7] app/test-pmd: add latency statistics calculation Remy Horton 2017-02-03 10:33 ` [dpdk-dev] [PATCH v10 0/7] Expanded statistics reporting Remy Horton 7 siblings, 0 replies; 115+ messages in thread From: Remy Horton @ 2017-01-18 15:05 UTC (permalink / raw) To: dev; +Cc: Harry van Haaren, Thomas Monjalon, Reshma Pattan From: Harry van Haaren <harry.van.haaren@intel.com> Add a library designed to calculate latency statistics and report them to the application when queried. The library measures minimum, average and maximum latencies, and jitter in nano seconds. The current implementation supports global latency stats, i.e. per application stats. Signed-off-by: Reshma Pattan <reshma.pattan@intel.com> Signed-off-by: Remy Horton <remy.horton@intel.com> Signed-off-by: Harry van Haaren <harry.van.haaren@intel.com> --- MAINTAINERS | 4 + config/common_base | 5 + doc/api/doxy-api-index.md | 1 + doc/api/doxy-api.conf | 1 + doc/guides/rel_notes/release_17_02.rst | 5 + lib/Makefile | 1 + lib/librte_latencystats/Makefile | 56 ++++ lib/librte_latencystats/rte_latencystats.c | 366 +++++++++++++++++++++ lib/librte_latencystats/rte_latencystats.h | 154 +++++++++ .../rte_latencystats_version.map | 11 + mk/rte.app.mk | 2 +- 11 files changed, 605 insertions(+), 1 deletion(-) create mode 100644 lib/librte_latencystats/Makefile create mode 100644 lib/librte_latencystats/rte_latencystats.c create mode 100644 lib/librte_latencystats/rte_latencystats.h create mode 100644 lib/librte_latencystats/rte_latencystats_version.map diff --git a/MAINTAINERS b/MAINTAINERS index d9423cb..03f53b7 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -604,6 +604,10 @@ Bit-rate statistica M: Remy Horton <remy.horton@intel.com> F: lib/librte_bitratestats/ +Latency Stats +M: Reshma Pattan <reshma.pattan@intel.com> +F: lib/librte_latencystats/ + Test Applications ----------------- diff --git a/config/common_base b/config/common_base index decebe5..762a54c 100644 --- a/config/common_base +++ b/config/common_base @@ -603,3 +603,8 @@ CONFIG_RTE_LIBRTE_METRICS=y # Compile the bitrate statistics library # CONFIG_RTE_LIBRTE_BITRATE=y + +# +# Compile the latency statistics library +# +CONFIG_RTE_LIBRTE_LATENCY_STATS=y diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md index 5e194b0..1cacacc 100644 --- a/doc/api/doxy-api-index.md +++ b/doc/api/doxy-api-index.md @@ -152,4 +152,5 @@ There are many libraries, so their headers may be grouped by topics: [keepalive] (@ref rte_keepalive.h), [Device Metrics] (@ref rte_metrics.h), [Bitrate Statistics] (@ref rte_bitrate.h), + [Latency stats] (@ref rte_latencystats.h), [version] (@ref rte_version.h) diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf index 6e6ab5c..0effece 100644 --- a/doc/api/doxy-api.conf +++ b/doc/api/doxy-api.conf @@ -47,6 +47,7 @@ INPUT = doc/api/doxy-api-index.md \ lib/librte_jobstats \ lib/librte_kni \ lib/librte_kvargs \ + lib/librte_latencystats \ lib/librte_lpm \ lib/librte_mbuf \ lib/librte_mempool \ diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst index 421270c..2203593 100644 --- a/doc/guides/rel_notes/release_17_02.rst +++ b/doc/guides/rel_notes/release_17_02.rst @@ -107,6 +107,10 @@ New Features See the :ref:`Virtio Interrupt Mode <virtio_interrupt_mode>` documentation for more information. +* **Added latency stats library.** + + A library that measures packet latency. The collected statistics are jitter + and latency. For latency the minimum, average, and maximum is measured. Resolved Issues --------------- @@ -228,6 +232,7 @@ The libraries prepended with a plus sign were incremented in this version. librte_jobstats.so.1 librte_kni.so.2 librte_kvargs.so.1 + + librte_latencystats.so.1 librte_lpm.so.2 librte_mbuf.so.2 librte_mempool.so.2 diff --git a/lib/Makefile b/lib/Makefile index e211bc0..6fffa88 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -60,6 +60,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_REORDER) += librte_reorder DIRS-$(CONFIG_RTE_LIBRTE_PDUMP) += librte_pdump DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics DIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += librte_bitratestats +DIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += librte_latencystats ifeq ($(CONFIG_RTE_EXEC_ENV_LINUXAPP),y) DIRS-$(CONFIG_RTE_LIBRTE_KNI) += librte_kni diff --git a/lib/librte_latencystats/Makefile b/lib/librte_latencystats/Makefile new file mode 100644 index 0000000..fd145d3 --- /dev/null +++ b/lib/librte_latencystats/Makefile @@ -0,0 +1,56 @@ +# BSD LICENSE +# +# Copyright(c) 2016-2017 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +include $(RTE_SDK)/mk/rte.vars.mk + +# library name +LIB = librte_latencystats.a + +CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3 +LDLIBS += -lm +LDLIBS += -lpthread + +EXPORT_MAP := rte_latencystats_version.map + +LIBABIVER := 1 + +# all source are stored in SRCS-y +SRCS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) := rte_latencystats.c + +# install this header file +SYMLINK-$(CONFIG_RTE_LIBRTE_LATENCY_STATS)-include := rte_latencystats.h + +# this lib depends upon: +DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_mbuf +DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_eal +DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_ether +DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_metrics + +include $(RTE_SDK)/mk/rte.lib.mk diff --git a/lib/librte_latencystats/rte_latencystats.c b/lib/librte_latencystats/rte_latencystats.c new file mode 100644 index 0000000..5334b8b --- /dev/null +++ b/lib/librte_latencystats/rte_latencystats.c @@ -0,0 +1,366 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016-2017 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <unistd.h> +#include <sys/types.h> +#include <stdbool.h> +#include <math.h> + +#include <rte_mbuf.h> +#include <rte_log.h> +#include <rte_cycles.h> +#include <rte_ethdev.h> +#include <rte_metrics.h> +#include <rte_memzone.h> +#include <rte_lcore.h> +#include <rte_timer.h> + +#include "rte_latencystats.h" + +/** Nano seconds per second */ +#define NS_PER_SEC 1E9 + +/** Clock cycles per nano second */ +static uint64_t +latencystat_cycles_per_ns(void) +{ + return rte_get_timer_hz() / NS_PER_SEC; +} + +/* Macros for printing using RTE_LOG */ +#define RTE_LOGTYPE_LATENCY_STATS RTE_LOGTYPE_USER1 + +static const char *MZ_RTE_LATENCY_STATS = "rte_latencystats"; +static int latency_stats_index; +static uint64_t samp_intvl; +static uint64_t timer_tsc; +static uint64_t prev_tsc; + +struct rte_latency_stats { + float min_latency; /**< Minimum latency in nano seconds */ + float avg_latency; /**< Average latency in nano seconds */ + float max_latency; /**< Maximum latency in nano seconds */ + float jitter; /** Latency variation */ +}; + +static struct rte_latency_stats *glob_stats; + +struct rxtx_cbs { + struct rte_eth_rxtx_callback *cb; +}; + +static struct rxtx_cbs rx_cbs[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT]; +static struct rxtx_cbs tx_cbs[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT]; + +struct latency_stats_nameoff { + char name[RTE_ETH_XSTATS_NAME_SIZE]; + unsigned int offset; +}; + +static const struct latency_stats_nameoff lat_stats_strings[] = { + {"min_latency_ns", offsetof(struct rte_latency_stats, min_latency)}, + {"avg_latency_ns", offsetof(struct rte_latency_stats, avg_latency)}, + {"max_latency_ns", offsetof(struct rte_latency_stats, max_latency)}, + {"jitter_ns", offsetof(struct rte_latency_stats, jitter)}, +}; + +#define NUM_LATENCY_STATS (sizeof(lat_stats_strings) / \ + sizeof(lat_stats_strings[0])) + +int32_t +rte_latencystats_update(void) +{ + unsigned int i; + float *stats_ptr = NULL; + uint64_t values[NUM_LATENCY_STATS] = {0}; + int ret; + + for (i = 0; i < NUM_LATENCY_STATS; i++) { + stats_ptr = RTE_PTR_ADD(glob_stats, + lat_stats_strings[i].offset); + values[i] = (uint64_t)floor((*stats_ptr)/ + latencystat_cycles_per_ns()); + } + + ret = rte_metrics_update_values(RTE_METRICS_GLOBAL, + latency_stats_index, + values, NUM_LATENCY_STATS); + if (ret < 0) + RTE_LOG(INFO, LATENCY_STATS, "Failed to push the stats\n"); + + return ret; +} + +static void +rte_latencystats_fill_values(struct rte_metric_value *values) +{ + unsigned int i; + float *stats_ptr = NULL; + + for (i = 0; i < NUM_LATENCY_STATS; i++) { + stats_ptr = RTE_PTR_ADD(glob_stats, + lat_stats_strings[i].offset); + values[i].key = i; + values[i].value = (uint64_t)floor((*stats_ptr)/ + latencystat_cycles_per_ns()); + } +} + +static uint16_t +add_time_stamps(uint8_t pid __rte_unused, + uint16_t qid __rte_unused, + struct rte_mbuf **pkts, + uint16_t nb_pkts, + uint16_t max_pkts __rte_unused, + void *user_cb __rte_unused) +{ + unsigned int i; + uint64_t diff_tsc, now; + + /* + * For every sample interval, + * time stamp is marked on one received packet. + */ + now = rte_rdtsc(); + for (i = 0; i < nb_pkts; i++) { + diff_tsc = now - prev_tsc; + timer_tsc += diff_tsc; + if (timer_tsc >= samp_intvl) { + /* + * TBD: Mark the timestamp only + * if not already marked by the + * hardware or the PMD. + */ + pkts[i]->timestamp = now; + timer_tsc = 0; + } + prev_tsc = now; + now = rte_rdtsc(); + } + + return nb_pkts; +} + +static uint16_t +calc_latency(uint8_t pid __rte_unused, + uint16_t qid __rte_unused, + struct rte_mbuf **pkts, + uint16_t nb_pkts, + void *_ __rte_unused) +{ + unsigned int i, cnt = 0; + uint64_t now; + float latency[nb_pkts]; + static float prev_latency; + /* + * Alpha represents degree of weighting decrease in EWMA, + * a constant smoothing factor between 0 and 1. The value + * is used below for measuring average latency. + */ + const float alpha = 0.2; + + now = rte_rdtsc(); + for (i = 0; i < nb_pkts; i++) { + if (pkts[i]->timestamp) + latency[cnt++] = now - pkts[i]->timestamp; + } + + for (i = 0; i < cnt; i++) { + /* + * The jitter is calculated as statistical mean of interpacket + * delay variation. The "jitter estimate" is computed by taking + * the absolute values of the ipdv sequence and applying an + * exponential filter with parameter 1/16 to generate the + * estimate. i.e J=J+(|D(i-1,i)|-J)/16. Where J is jitter, + * D(i-1,i) is difference in latency of two consecutive packets + * i-1 and i. + * Reference: Calculated as per RFC 5481, sec 4.1, + * RFC 3393 sec 4.5, RFC 1889 sec. + */ + glob_stats->jitter += (abs(prev_latency - latency[i]) + - glob_stats->jitter)/16; + if (glob_stats->min_latency == 0) + glob_stats->min_latency = latency[i]; + else if (latency[i] < glob_stats->min_latency) + glob_stats->min_latency = latency[i]; + else if (latency[i] > glob_stats->max_latency) + glob_stats->max_latency = latency[i]; + /* + * The average latency is measured using exponential moving + * average, i.e. using EWMA + * https://en.wikipedia.org/wiki/Moving_average + */ + glob_stats->avg_latency += + alpha * (latency[i] - glob_stats->avg_latency); + prev_latency = latency[i]; + } + + return nb_pkts; +} + +int +rte_latencystats_init(uint64_t app_samp_intvl, + rte_latency_stats_flow_type_fn user_cb) +{ + unsigned int i; + uint8_t pid; + uint16_t qid; + struct rxtx_cbs *cbs = NULL; + const uint8_t nb_ports = rte_eth_dev_count(); + const char *ptr_strings[NUM_LATENCY_STATS] = {0}; + const struct rte_memzone *mz = NULL; + const unsigned int flags = 0; + + if (rte_memzone_lookup(MZ_RTE_LATENCY_STATS)) + return -EEXIST; + + /** Allocate stats in shared memory fo multi process support */ + mz = rte_memzone_reserve(MZ_RTE_LATENCY_STATS, sizeof(*glob_stats), + rte_socket_id(), flags); + if (mz == NULL) { + RTE_LOG(ERR, LATENCY_STATS, "Cannot reserve memory: %s:%d\n", + __func__, __LINE__); + return -ENOMEM; + } + + glob_stats = mz->addr; + samp_intvl = app_samp_intvl * latencystat_cycles_per_ns(); + + /** Register latency stats with stats library */ + for (i = 0; i < NUM_LATENCY_STATS; i++) + ptr_strings[i] = lat_stats_strings[i].name; + + latency_stats_index = rte_metrics_reg_names(ptr_strings, + NUM_LATENCY_STATS); + if (latency_stats_index < 0) { + RTE_LOG(DEBUG, LATENCY_STATS, + "Failed to register latency stats names\n"); + return -1; + } + + /** Register Rx/Tx callbacks */ + for (pid = 0; pid < nb_ports; pid++) { + struct rte_eth_dev_info dev_info; + rte_eth_dev_info_get(pid, &dev_info); + for (qid = 0; qid < dev_info.nb_rx_queues; qid++) { + cbs = &rx_cbs[pid][qid]; + cbs->cb = rte_eth_add_first_rx_callback(pid, qid, + add_time_stamps, user_cb); + if (!cbs->cb) + RTE_LOG(INFO, LATENCY_STATS, "Failed to " + "register Rx callback for pid=%d, " + "qid=%d\n", pid, qid); + } + for (qid = 0; qid < dev_info.nb_tx_queues; qid++) { + cbs = &tx_cbs[pid][qid]; + cbs->cb = rte_eth_add_tx_callback(pid, qid, + calc_latency, user_cb); + if (!cbs->cb) + RTE_LOG(INFO, LATENCY_STATS, "Failed to " + "register Tx callback for pid=%d, " + "qid=%d\n", pid, qid); + } + } + return 0; +} + +int +rte_latencystats_uninit(void) +{ + uint8_t pid; + uint16_t qid; + int ret = 0; + struct rxtx_cbs *cbs = NULL; + const uint8_t nb_ports = rte_eth_dev_count(); + + /** De register Rx/Tx callbacks */ + for (pid = 0; pid < nb_ports; pid++) { + struct rte_eth_dev_info dev_info; + rte_eth_dev_info_get(pid, &dev_info); + for (qid = 0; qid < dev_info.nb_rx_queues; qid++) { + cbs = &rx_cbs[pid][qid]; + ret = rte_eth_remove_rx_callback(pid, qid, cbs->cb); + if (ret) + RTE_LOG(INFO, LATENCY_STATS, "failed to " + "remove Rx callback for pid=%d, " + "qid=%d\n", pid, qid); + } + for (qid = 0; qid < dev_info.nb_tx_queues; qid++) { + cbs = &tx_cbs[pid][qid]; + ret = rte_eth_remove_tx_callback(pid, qid, cbs->cb); + if (ret) + RTE_LOG(INFO, LATENCY_STATS, "failed to " + "remove Tx callback for pid=%d, " + "qid=%d\n", pid, qid); + } + } + + return 0; +} + +int +rte_latencystats_get_names(struct rte_metric_name *names, uint16_t size) +{ + unsigned int i; + + if (names == NULL || size < NUM_LATENCY_STATS) + return NUM_LATENCY_STATS; + + for (i = 0; i < NUM_LATENCY_STATS; i++) + snprintf(names[i].name, sizeof(names[i].name), + "%s", lat_stats_strings[i].name); + + return NUM_LATENCY_STATS; +} + +int +rte_latencystats_get(struct rte_metric_value *values, uint16_t size) +{ + if (size < NUM_LATENCY_STATS || values == NULL) + return NUM_LATENCY_STATS; + + if (rte_eal_process_type() == RTE_PROC_SECONDARY) { + const struct rte_memzone *mz; + mz = rte_memzone_lookup(MZ_RTE_LATENCY_STATS); + if (mz == NULL) { + RTE_LOG(ERR, LATENCY_STATS, + "Latency stats memzone not found\n"); + return -ENOMEM; + } + glob_stats = mz->addr; + } + + /* Retrieve latency stats */ + rte_latencystats_fill_values(values); + + return NUM_LATENCY_STATS; +} diff --git a/lib/librte_latencystats/rte_latencystats.h b/lib/librte_latencystats/rte_latencystats.h new file mode 100644 index 0000000..28c6dcf --- /dev/null +++ b/lib/librte_latencystats/rte_latencystats.h @@ -0,0 +1,154 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016-2017 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _RTE_LATENCYSTATS_H_ +#define _RTE_LATENCYSTATS_H_ + +/** + * @file + * RTE latency stats + * + * library to provide application and flow based latency stats. + */ + +#include <rte_metrics.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Note: This function pointer is for future flow based latency stats + * implementation. + * + * Function type used for identifting flow types of a Rx packet. + * + * The callback function is called on Rx for each packet. + * This function is used for flow based latency calculations. + * + * @param pkt + * Packet that has to be identified with its flow types. + * @param user_param + * The arbitrary user parameter passed in by the application when + * the callback was originally configured. + * @return + * The flow_mask, representing the multiple flow types of a packet. + */ +typedef uint16_t (*rte_latency_stats_flow_type_fn)(struct rte_mbuf *pkt, + void *user_param); + +/** + * Registers Rx/Tx callbacks for each active port, queue. + * + * @param samp_intvl + * Sampling time period in nano seconds, at which packet + * should be marked with time stamp. + * @param user_cb + * Note: This param is for future flow based latency stats + * implementation. + * User callback to be called to get flow types of a packet. + * Used for flow based latency calculation. + * If the value is NULL, global stats will be calculated, + * else flow based latency stats will be calculated. + * For now just pass on the NULL value to this param. + * @return + * -1 : On error + * -ENOMEM: On error + * 0 : On success + */ +int rte_latencystats_init(uint64_t samp_intvl, + rte_latency_stats_flow_type_fn user_cb); + +/** + * Calculates the latency and jitter values internally, exposing the updated + * values via *rte_latencystats_get* or the rte_metrics API. + * @return: + * 0 : on Success + * < 0 : Error in updating values. + */ +int32_t rte_latencystats_update(void); + +/** + * Removes registered Rx/Tx callbacks for each active port, queue. + * + * @return + * -1: On error + * 0: On success + */ +int rte_latencystats_uninit(void); + +/** + * Retrieve names of latency statistics + * + * @param names + * Block of memory to insert names into. Must be at least size in capacity. + * If set to NULL, function returns required capacity. + * @param size + * Capacity of latency stats names (number of names). + * @return + * - positive value lower or equal to size: success. The return value + * is the number of entries filled in the stats table. + * - positive value higher than size: error, the given statistics table + * is too small. The return value corresponds to the size that should + * be given to succeed. The entries in the table are not valid and + * shall not be used by the caller. + */ +int rte_latencystats_get_names(struct rte_metric_name *names, + uint16_t size); + +/** + * Retrieve latency statistics. + * + * @param values + * A pointer to a table of structure of type *rte_metric_value* + * to be filled with latency statistics ids and values. + * This parameter can be set to NULL if size is 0. + * @param size + * The size of the stats table, which should be large enough to store + * all the latency stats. + * @return + * - positive value lower or equal to size: success. The return value + * is the number of entries filled in the stats table. + * - positive value higher than size: error, the given statistics table + * is too small. The return value corresponds to the size that should + * be given to succeed. The entries in the table are not valid and + * shall not be used by the caller. + * -ENOMEM: On failure. + */ +int rte_latencystats_get(struct rte_metric_value *values, + uint16_t size); + +#ifdef __cplusplus +} +#endif + +#endif /* _RTE_LATENCYSTATS_H_ */ diff --git a/lib/librte_latencystats/rte_latencystats_version.map b/lib/librte_latencystats/rte_latencystats_version.map new file mode 100644 index 0000000..d240563 --- /dev/null +++ b/lib/librte_latencystats/rte_latencystats_version.map @@ -0,0 +1,11 @@ +DPDK_17.02 { + global: + + rte_latencystats_get; + rte_latencystats_get_names; + rte_latencystats_init; + rte_latencystats_uninit; + rte_latencystats_update; + + local: *; +}; diff --git a/mk/rte.app.mk b/mk/rte.app.mk index 6aac5ac..1d36fad 100644 --- a/mk/rte.app.mk +++ b/mk/rte.app.mk @@ -100,7 +100,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE) += -lrte_cmdline _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE) += -lrte_cfgfile _LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS) += -lrte_metrics _LDLIBS-$(CONFIG_RTE_LIBRTE_BITRATE) += -lrte_bitratestats - +_LDLIBS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += -lrte_latencystats _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += -lrte_pmd_bond _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += -lrte_pmd_xenvirt -lxenstore -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v9 7/7] app/test-pmd: add latency statistics calculation 2017-01-18 15:05 ` [dpdk-dev] [PATCH v9 0/7] Expanded statistics reporting Remy Horton ` (5 preceding siblings ...) 2017-01-18 15:05 ` [dpdk-dev] [PATCH v9 6/7] lib: added new library for latency stats Remy Horton @ 2017-01-18 15:05 ` Remy Horton 2017-02-03 10:33 ` [dpdk-dev] [PATCH v10 0/7] Expanded statistics reporting Remy Horton 7 siblings, 0 replies; 115+ messages in thread From: Remy Horton @ 2017-01-18 15:05 UTC (permalink / raw) To: dev; +Cc: Harry van Haaren, Thomas Monjalon, Reshma Pattan From: Harry van Haaren <harry.van.haaren@intel.com> This patch adds latency stats commandline argument to testpmd, allowing to specify the lcore to use for latencystats updates. Signed-off-by: Reshma Pattan <reshma.pattan@intel.com> Signed-off-by: Harry van Haaren <harry.van.haaren@intel.com> Signed-off-by: Remy Horton <remy.horton@intel.com> --- app/test-pmd/parameters.c | 20 +++++++++++++++++++- app/test-pmd/testpmd.c | 37 +++++++++++++++++++++++++++++++++++++ app/test-pmd/testpmd.h | 6 +++++- 3 files changed, 61 insertions(+), 2 deletions(-) diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c index 28db8cd..30b60ba 100644 --- a/app/test-pmd/parameters.c +++ b/app/test-pmd/parameters.c @@ -1,7 +1,7 @@ /*- * BSD LICENSE * - * Copyright(c) 2010-2016 Intel Corporation. All rights reserved. + * Copyright(c) 2010-2017 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -149,6 +149,10 @@ usage(char* progname) "the packet will be enqueued into the rx drop-queue. " "If the drop-queue doesn't exist, the packet is dropped. " "By default drop-queue=127.\n"); +#ifdef RTE_LIBRTE_LATENCY_STATS + printf(" --latencystats=N: enable latency and jitter statistcs " + "monitoring on lcore id N.\n"); +#endif printf(" --crc-strip: enable CRC stripping by hardware.\n"); printf(" --enable-lro: enable large receive offload.\n"); printf(" --enable-rx-cksum: enable rx hardware checksum offload.\n"); @@ -526,6 +530,7 @@ launch_args_parse(int argc, char** argv) { "pkt-filter-report-hash", 1, 0, 0 }, { "pkt-filter-size", 1, 0, 0 }, { "pkt-filter-drop-queue", 1, 0, 0 }, + { "latencystats", 1, 0, 0 }, { "crc-strip", 0, 0, 0 }, { "enable-lro", 0, 0, 0 }, { "enable-rx-cksum", 0, 0, 0 }, @@ -766,6 +771,19 @@ launch_args_parse(int argc, char** argv) "drop queue %d invalid - must" "be >= 0 \n", n); } +#ifdef RTE_LIBRTE_LATENCY_STATS + if (!strcmp(lgopts[opt_idx].name, + "latencystats")) { + n = atoi(optarg); + if (n >= 0) { + latencystats_lcore_id = (lcoreid_t) n; + latencystats_enabled = 1; + } else + rte_exit(EXIT_FAILURE, + "invalid lcore id %d for latencystats" + " must be >= 0\n", n); + } +#endif if (!strcmp(lgopts[opt_idx].name, "crc-strip")) rx_mode.hw_strip_crc = 1; if (!strcmp(lgopts[opt_idx].name, "enable-lro")) diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c index b31a300..524e758 100644 --- a/app/test-pmd/testpmd.c +++ b/app/test-pmd/testpmd.c @@ -83,6 +83,10 @@ #ifdef RTE_LIBRTE_BITRATE #include <rte_bitrate.h> #endif +#include <rte_metrics.h> +#ifdef RTE_LIBRTE_LATENCY_STATS +#include <rte_latencystats.h> +#endif #include "testpmd.h" @@ -276,6 +280,20 @@ uint32_t bypass_timeout = RTE_BYPASS_TMT_OFF; #endif +#ifdef RTE_LIBRTE_LATENCY_STATS + +/* + * Set when latency stats is enabled in the commandline + */ +uint8_t latencystats_enabled; + +/* + * Lcore ID to serive latency statistics. + */ +lcoreid_t latencystats_lcore_id = -1; + +#endif + /* * Ethernet device configuration. */ @@ -955,6 +973,11 @@ run_pkt_fwd_on_lcore(struct fwd_lcore *fc, packet_fwd_t pkt_fwd) tics_datum = tics_current; } #endif +#ifdef RTE_LIBRTE_LATENCY_STATS + if (latencystats_lcore_id == rte_lcore_id()) + rte_latencystats_update(); +#endif + } while (! fc->stopped); } @@ -2108,6 +2131,9 @@ signal_handler(int signum) /* uninitialize packet capture framework */ rte_pdump_uninit(); #endif +#ifdef RTE_LIBRTE_LATENCY_STATS + rte_latencystats_uninit(); +#endif force_quit(); /* exit with the expected status */ signal(signum, SIG_DFL); @@ -2169,6 +2195,17 @@ main(int argc, char** argv) /* Init metrics library */ rte_metrics_init(rte_socket_id()); +#ifdef RTE_LIBRTE_LATENCY_STATS + if (latencystats_enabled != 0) { + int ret = rte_latencystats_init(1, NULL); + if (ret) + printf("Warning: latencystats init()" + " returned error %d\n", ret); + printf("Latencystats running on lcore %d\n", + latencystats_lcore_id); + } +#endif + /* Setup bitrate stats */ #ifdef RTE_LIBRTE_BITRATE bitrate_data = rte_stats_bitrate_create(); diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h index 0a9a1af..35f7477 100644 --- a/app/test-pmd/testpmd.h +++ b/app/test-pmd/testpmd.h @@ -1,7 +1,7 @@ /*- * BSD LICENSE * - * Copyright(c) 2010-2016 Intel Corporation. All rights reserved. + * Copyright(c) 2010-2017 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -381,6 +381,10 @@ extern enum dcb_queue_mapping_mode dcb_q_mapping; extern uint16_t mbuf_data_size; /**< Mbuf data space size. */ extern uint32_t param_total_num_mbufs; + +extern uint8_t latencystats_enabled; +extern lcoreid_t latencystats_lcore_id; + extern struct rte_fdir_conf fdir_conf; /* -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v10 0/7] Expanded statistics reporting 2017-01-18 15:05 ` [dpdk-dev] [PATCH v9 0/7] Expanded statistics reporting Remy Horton ` (6 preceding siblings ...) 2017-01-18 15:05 ` [dpdk-dev] [PATCH v9 7/7] app/test-pmd: add latency statistics calculation Remy Horton @ 2017-02-03 10:33 ` Remy Horton 2017-02-03 10:33 ` [dpdk-dev] [PATCH v10 1/7] lib: add information metrics library Remy Horton ` (8 more replies) 7 siblings, 9 replies; 115+ messages in thread From: Remy Horton @ 2017-02-03 10:33 UTC (permalink / raw) To: dev; +Cc: Thomas Monjalon This patchset extends statistics reporting to include peak and average data-rate metrics. It comes in two parts: a statistics reporting library, and a bitrate calculation library that uses it. This structure is intended to seperate statistic reporting from ethdev and allow more flexible metric registration. -- v10 changes: * Rebased * Relocated some config-related directives. * Removed incorrect capitalisations in API docs. * Formatting & detail corrections in release notes. * Moved around struct member descriptions. * Rewritten rte_metrics.h file description. * Rewritten description of RTE_METRICS_GLOBAL. * Used 'producers' and 'consumers' as terms. * Removed markup (bold text) in Doxygen tags. * Added programming guide section. v9 changes: * Updated .map files to reflect function changes in v8 * Fixed rte_malloc() of zero bytes in proc_info when no metrics exist * Fixed rte_metrics_init not being called explicitly in testpmd v8 changes: * Release notes correction * Updated copyright years * rte_metric_init() takes socket id & must be explicitly called * rte_metrics_reg_metric renamed to rte_metrics_reg_name() * rte_metrics_update_metric() renamed to rte_metrics_update_value() * Doxygen updates * Changed malloc()/free() to rte_malloc()/rte_free() * Removed redundant memset() * rte_stats_bitrates_s renamed to rte_stats_bitrates_s * Split mbuf change to own patch for visibility * CYCLES_PER_NS now a static inline function * latency: "hidden" pthread creation now has polling API instead. * Struct declarations and variable definitions cleaned up * Double initialization of the latency library now returns -EEXIST * MAINTAINERS entry for layenctstats in correct section v7 changes: * RTE_METRICS_NONPORT renamed to RTE_METRICS_GLOBAL * Multiple changes to rte_metrics.h doxygen documentation * Split apart latency patch into lib, test-pmd, & proc_info parts * Reordered patches by functionality * Insufficent capacity return value changed from -ERANGE to actual size * Cache alignment in bitrate library * Tightened up const usage to avoid STATIC_CONST_CHAR_ARRAY warning * Reshma reinstated as author for (now split) latency patch * Rebase to master v6 changes: * Metrics display now has "Non port specific" rather than "port -1" * Fixed sign issue in EWMA delta calculation * Rebased to master v5 changes: * Updated Shared Library Versions in release notes * Merged in Reshma's latencystats library v4 changes: * References to 16.11 changed to 17.02 * Fetching of non-port values was broken * Added sanity checks to value fetching * rte_stat_value renamed to rte_metric_value * Corrected doxygen descriptions * Added MAINTAINERS entries * Added #ifdef directives to bitrate code in test-pmd v3 changes: * Marked rte_stats_bitrate_s as internal * Minor integer roundoff correction * Coding style corrections * Removed spurious object allocation * Changes to rte_metrics.[ch] moved from Patch 2/3 to 1/3. * Reintroduced non-port values (RTE_METRICS_NONPORT) * Added spinlocks to metric library * Removed spurious test registration/update * Added release notes entries v2 changes: * Uses a new metrics library rather than being part of ethdev Harry van Haaren (3): mbuf: add a timestamp to the mbuf for latencystats lib: added new library for latency stats app/test-pmd: add latency statistics calculation Remy Horton (3): lib: add information metrics library lib: add bitrate statistics library app/test-pmd: add bitrate statistics calculation Reshma Pattan (1): app/proc_info: add metrics displaying MAINTAINERS | 12 + app/proc_info/main.c | 79 ++++- app/test-pmd/parameters.c | 20 +- app/test-pmd/testpmd.c | 78 ++++- app/test-pmd/testpmd.h | 6 +- config/common_base | 15 + doc/api/doxy-api-index.md | 3 + doc/api/doxy-api.conf | 3 + doc/guides/prog_guide/index.rst | 1 + doc/guides/prog_guide/metrics_lib.rst | 297 +++++++++++++++++ doc/guides/rel_notes/release_17_02.rst | 20 ++ lib/Makefile | 3 + lib/librte_bitratestats/Makefile | 53 +++ lib/librte_bitratestats/rte_bitrate.c | 132 ++++++++ lib/librte_bitratestats/rte_bitrate.h | 80 +++++ .../rte_bitratestats_version.map | 9 + lib/librte_latencystats/Makefile | 56 ++++ lib/librte_latencystats/rte_latencystats.c | 366 +++++++++++++++++++++ lib/librte_latencystats/rte_latencystats.h | 154 +++++++++ .../rte_latencystats_version.map | 11 + lib/librte_mbuf/rte_mbuf.h | 3 + lib/librte_metrics/Makefile | 51 +++ lib/librte_metrics/rte_metrics.c | 299 +++++++++++++++++ lib/librte_metrics/rte_metrics.h | 240 ++++++++++++++ lib/librte_metrics/rte_metrics_version.map | 13 + mk/rte.app.mk | 3 + 26 files changed, 2003 insertions(+), 4 deletions(-) create mode 100644 doc/guides/prog_guide/metrics_lib.rst create mode 100644 lib/librte_bitratestats/Makefile create mode 100644 lib/librte_bitratestats/rte_bitrate.c create mode 100644 lib/librte_bitratestats/rte_bitrate.h create mode 100644 lib/librte_bitratestats/rte_bitratestats_version.map create mode 100644 lib/librte_latencystats/Makefile create mode 100644 lib/librte_latencystats/rte_latencystats.c create mode 100644 lib/librte_latencystats/rte_latencystats.h create mode 100644 lib/librte_latencystats/rte_latencystats_version.map create mode 100644 lib/librte_metrics/Makefile create mode 100644 lib/librte_metrics/rte_metrics.c create mode 100644 lib/librte_metrics/rte_metrics.h create mode 100644 lib/librte_metrics/rte_metrics_version.map -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v10 1/7] lib: add information metrics library 2017-02-03 10:33 ` [dpdk-dev] [PATCH v10 0/7] Expanded statistics reporting Remy Horton @ 2017-02-03 10:33 ` Remy Horton 2017-02-03 10:33 ` [dpdk-dev] [PATCH v10 2/7] app/proc_info: add metrics displaying Remy Horton ` (7 subsequent siblings) 8 siblings, 0 replies; 115+ messages in thread From: Remy Horton @ 2017-02-03 10:33 UTC (permalink / raw) To: dev; +Cc: Thomas Monjalon This patch adds a new information metrics library. This Metrics library implements a mechanism by which producers can publish numeric information for later querying by consumers. Metrics themselves are statistics that are not generated by PMDs, and hence are not reported via ethdev extended statistics. Metric information is populated using a push model, where producers update the values contained within the metric library by calling an update function on the relevant metrics. Consumers receive metric information by querying the central metric data, which is held in shared memory. Signed-off-by: Remy Horton <remy.horton@intel.com> --- MAINTAINERS | 4 + config/common_base | 5 + doc/api/doxy-api-index.md | 1 + doc/api/doxy-api.conf | 1 + doc/guides/prog_guide/index.rst | 1 + doc/guides/prog_guide/metrics_lib.rst | 180 +++++++++++++++++ doc/guides/rel_notes/release_17_02.rst | 9 + lib/Makefile | 1 + lib/librte_metrics/Makefile | 51 +++++ lib/librte_metrics/rte_metrics.c | 299 +++++++++++++++++++++++++++++ lib/librte_metrics/rte_metrics.h | 240 +++++++++++++++++++++++ lib/librte_metrics/rte_metrics_version.map | 13 ++ mk/rte.app.mk | 2 + 13 files changed, 807 insertions(+) create mode 100644 doc/guides/prog_guide/metrics_lib.rst create mode 100644 lib/librte_metrics/Makefile create mode 100644 lib/librte_metrics/rte_metrics.c create mode 100644 lib/librte_metrics/rte_metrics.h create mode 100644 lib/librte_metrics/rte_metrics_version.map diff --git a/MAINTAINERS b/MAINTAINERS index 27f999b..eceebaa 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -627,6 +627,10 @@ F: lib/librte_jobstats/ F: examples/l2fwd-jobstats/ F: doc/guides/sample_app_ug/l2_forward_job_stats.rst +Metrics +M: Remy Horton <remy.horton@intel.com> +F: lib/librte_metrics/ + Test Applications ----------------- diff --git a/config/common_base b/config/common_base index 71a4fcb..b819932 100644 --- a/config/common_base +++ b/config/common_base @@ -501,6 +501,11 @@ CONFIG_RTE_LIBRTE_EFD=y CONFIG_RTE_LIBRTE_JOBSTATS=y # +# Compile the device metrics library +# +CONFIG_RTE_LIBRTE_METRICS=y + +# # Compile librte_lpm # CONFIG_RTE_LIBRTE_LPM=y diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md index eb39f69..26a26b7 100644 --- a/doc/api/doxy-api-index.md +++ b/doc/api/doxy-api-index.md @@ -156,4 +156,5 @@ There are many libraries, so their headers may be grouped by topics: [common] (@ref rte_common.h), [ABI compat] (@ref rte_compat.h), [keepalive] (@ref rte_keepalive.h), + [device metrics] (@ref rte_metrics.h), [version] (@ref rte_version.h) diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf index b8a5fd8..e2e070f 100644 --- a/doc/api/doxy-api.conf +++ b/doc/api/doxy-api.conf @@ -53,6 +53,7 @@ INPUT = doc/api/doxy-api-index.md \ lib/librte_mbuf \ lib/librte_mempool \ lib/librte_meter \ + lib/librte_metrics \ lib/librte_net \ lib/librte_pdump \ lib/librte_pipeline \ diff --git a/doc/guides/prog_guide/index.rst b/doc/guides/prog_guide/index.rst index 7f825cb..fea651c 100644 --- a/doc/guides/prog_guide/index.rst +++ b/doc/guides/prog_guide/index.rst @@ -62,6 +62,7 @@ Programmer's Guide packet_classif_access_ctrl packet_framework vhost_lib + metrics_lib port_hotplug_framework source_org dev_kit_build_system diff --git a/doc/guides/prog_guide/metrics_lib.rst b/doc/guides/prog_guide/metrics_lib.rst new file mode 100644 index 0000000..87f806d --- /dev/null +++ b/doc/guides/prog_guide/metrics_lib.rst @@ -0,0 +1,180 @@ +.. BSD LICENSE + Copyright(c) 2017 Intel Corporation. All rights reserved. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +.. _Metrics_Library: + +Metrics Library +=============== + +The Metrics library implements a mechanism by which *producers* can +publish numeric information for later querying by *consumers*. In +practice producers will typically be other libraries or primary +processes, whereas consumers will typically be applications. + +Metrics themselves are statistics that are not generated by PMDs. Metric +information is populated using a push model, where producers update the +values contained within the metric library by calling an update function +on the relevant metrics. Consumers receive metric information by querying +the central metric data, which is held in shared memory. + +For each metric, a separate value is maintained for each port id, and +when publishing metric values the producers need to specify which port is +being updated. In addition there is a special id ``RTE_METRICS_GLOBAL`` +that is intended for global statistics that are not associated with any +individual device. Since the metrics library is self-contained, the only +restriction on port numbers is that they are less than ``RTE_MAX_ETHPORTS`` +- there is no requirement for the ports to actually exist. + +Initialising the library +------------------------ + +Before the library can be used, it has to be initialized by calling +``rte_metrics_init()`` which sets up the metric store in shared memory. +This is where producers will publish metric information to, and where +consumers will query it from. + +.. code-block:: c + + rte_metrics_init(rte_socket_id()); + +This function **must** be called from a primary process, but otherwise +producers and consumers can be in either primary or secondary processes. + +Registering metrics +------------------- + +Metrics must first be *registered*, which is the way producers declare +the names of the metrics they will be publishing. Registration can either +be done individually, or a set of metrics can be registered as a group. +Individual registration is done using ``rte_metrics_reg_name()``: + +.. code-block:: c + + id_1 = rte_metrics_reg_name("mean_bits_in"); + id_2 = rte_metrics_reg_name("mean_bits_out"); + id_3 = rte_metrics_reg_name("peak_bits_in"); + id_4 = rte_metrics_reg_name("peak_bits_out"); + +or alternatively, a set of metrics can be registered together using +``rte_metrics_reg_names()``: + +.. code-block:: c + + const char * const names[] = { + "mean_bits_in", "mean_bits_out", + "peak_bits_in", "peak_bits_out", + }; + id_set = rte_metrics_reg_names(&names[0], 4); + +If the return value is negative, it means registration failed. Otherwise +the return value is the *key* for the metric, which is used when updating +values. A table mapping together these key values and the metrics' names +can be obtained using ``rte_metrics_get_names()``. + +Updating metric values +---------------------- + +Once registered, producers can update the metric for a given port using +the ``rte_metrics_update_value()`` function. This uses the metric key +that is returned when registering the metric, and can also be looked up +using ``rte_metrics_get_names()``. + +.. code-block:: c + + rte_metrics_update_value(port_id, id_1, values[0]); + rte_metrics_update_value(port_id, id_2, values[1]); + rte_metrics_update_value(port_id, id_3, values[2]); + rte_metrics_update_value(port_id, id_4, values[3]); + +if metrics were registered as a single set, they can either be updated +individually using ``rte_metrics_update_value()``, or updated together +using the ``rte_metrics_update_values()`` function: + +.. code-block:: c + + rte_metrics_update_value(port_id, id_set, values[0]); + rte_metrics_update_value(port_id, id_set + 1, values[1]); + rte_metrics_update_value(port_id, id_set + 2, values[2]); + rte_metrics_update_value(port_id, id_set + 3, values[3]); + + rte_metrics_update_values(port_id, id_set, values, 4); + +Note that ``rte_metrics_update_values()`` cannot be used to update +metric values from *multiple* *sets*, as there is no guarantee two +sets registered one after the other have contiguous id values. + +Querying metrics +---------------- + +Consumers can obtain metric values by querying the metrics library using +the ``rte_metrics_get_values()`` function that return an array of +``struct rte_metric_value``. Each entry within this array contains a metric +value and its associated key. A key-name mapping can be obtained using the +``rte_metrics_get_names()`` function that returns an array of +``struct rte_metric_name`` that is indexed by the key. The following will +print out all metrics for a given port: + +.. code-block:: c + + void print_metrics() { + struct rte_metric_name *names; + int len; + + len = rte_metrics_get_names(NULL, 0); + if (len < 0) { + printf("Cannot get metrics count\n"); + return; + } + if (len == 0) { + printf("No metrics to display (none have been registered)\n"); + return; + } + metrics = malloc(sizeof(struct rte_metric_value) * len); + names = malloc(sizeof(struct rte_metric_name) * len); + if (metrics == NULL || names == NULL) { + printf("Cannot allocate memory\n"); + free(metrics); + free(names); + return; + } + ret = rte_metrics_get_values(port_id, metrics, len); + if (ret < 0 || ret > len) { + printf("Cannot get metrics values\n"); + free(metrics); + free(names); + return; + } + printf("Metrics for port %i:\n", port_id); + for (i = 0; i < len; i++) + printf(" %s: %"PRIu64"\n", + names[metrics[i].key].name, metrics[i].value); + free(metrics); + free(names); + } diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst index 83519dc..68581e4 100644 --- a/doc/guides/rel_notes/release_17_02.rst +++ b/doc/guides/rel_notes/release_17_02.rst @@ -38,6 +38,14 @@ New Features Also, make sure to start the actual text at the margin. ========================================================= +* **Added information metric library.** + + A library that allows information metrics to be added and updated + by producers, typically other libraries, for later retrieval by + consumers such as applications. It is intended to provide a + reporting mechanism that is independent of other libraries such + as ethdev. + * **Added generic EAL API for I/O device memory read/write operations.** This API introduces 8-bit, 16-bit, 32bit, 64bit I/O device @@ -355,6 +363,7 @@ The libraries prepended with a plus sign were incremented in this version. librte_mbuf.so.2 librte_mempool.so.2 librte_meter.so.1 + + librte_metrics.so.1 librte_net.so.1 librte_pdump.so.1 librte_pipeline.so.3 diff --git a/lib/Makefile b/lib/Makefile index 4178325..29f6a81 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -49,6 +49,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_ACL) += librte_acl DIRS-$(CONFIG_RTE_LIBRTE_NET) += librte_net DIRS-$(CONFIG_RTE_LIBRTE_IP_FRAG) += librte_ip_frag DIRS-$(CONFIG_RTE_LIBRTE_JOBSTATS) += librte_jobstats +DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics DIRS-$(CONFIG_RTE_LIBRTE_POWER) += librte_power DIRS-$(CONFIG_RTE_LIBRTE_METER) += librte_meter DIRS-$(CONFIG_RTE_LIBRTE_SCHED) += librte_sched diff --git a/lib/librte_metrics/Makefile b/lib/librte_metrics/Makefile new file mode 100644 index 0000000..8d6e23a --- /dev/null +++ b/lib/librte_metrics/Makefile @@ -0,0 +1,51 @@ +# BSD LICENSE +# +# Copyright(c) 2016 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +include $(RTE_SDK)/mk/rte.vars.mk + +# library name +LIB = librte_metrics.a + +CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) + +EXPORT_MAP := rte_metrics_version.map + +LIBABIVER := 1 + +# all source are stored in SRCS-y +SRCS-$(CONFIG_RTE_LIBRTE_METRICS) := rte_metrics.c + +# Install header file +SYMLINK-$(CONFIG_RTE_LIBRTE_METRICS)-include += rte_metrics.h + +DEPDIRS-$(CONFIG_RTE_LIBRTE_METRICS) += lib/librte_eal + +include $(RTE_SDK)/mk/rte.lib.mk diff --git a/lib/librte_metrics/rte_metrics.c b/lib/librte_metrics/rte_metrics.c new file mode 100644 index 0000000..889d377 --- /dev/null +++ b/lib/librte_metrics/rte_metrics.c @@ -0,0 +1,299 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016-2017 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <string.h> +#include <sys/queue.h> + +#include <rte_common.h> +#include <rte_malloc.h> +#include <rte_metrics.h> +#include <rte_lcore.h> +#include <rte_memzone.h> +#include <rte_spinlock.h> + +#define RTE_METRICS_MAX_METRICS 256 +#define RTE_METRICS_MEMZONE_NAME "RTE_METRICS" + +/** + * Internal stats metadata and value entry. + * + * @internal + */ +struct rte_metrics_meta_s { + /** Name of metric */ + char name[RTE_METRICS_MAX_NAME_LEN]; + /** Current value for metric */ + uint64_t value[RTE_MAX_ETHPORTS]; + /** Used for global metrics */ + uint64_t nonport_value; + /** Index of next root element (zero for none) */ + uint16_t idx_next_set; + /** Index of next metric in set (zero for none) */ + uint16_t idx_next_stat; +}; + +/** + * Internal stats info structure. + * + * @internal + * Offsets into metadata are used instead of pointers because ASLR + * means that having the same physical addresses in different + * processes is not guaranteed. + */ +struct rte_metrics_data_s { + /** Index of last metadata entry with valid data. + * This value is not valid if cnt_stats is zero. + */ + uint16_t idx_last_set; + /** Number of metrics. */ + uint16_t cnt_stats; + /** Metric data memory block. */ + struct rte_metrics_meta_s metadata[RTE_METRICS_MAX_METRICS]; + /** Metric data access lock */ + rte_spinlock_t lock; +}; + +void +rte_metrics_init(int socket_id) +{ + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + + if (rte_eal_process_type() != RTE_PROC_PRIMARY) + return; + + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); + if (memzone != NULL) + return; + memzone = rte_memzone_reserve(RTE_METRICS_MEMZONE_NAME, + sizeof(struct rte_metrics_data_s), socket_id, 0); + if (memzone == NULL) + rte_exit(EXIT_FAILURE, "Unable to allocate stats memzone\n"); + stats = memzone->addr; + memset(stats, 0, sizeof(struct rte_metrics_data_s)); + rte_spinlock_init(&stats->lock); +} + +int +rte_metrics_reg_name(const char *name) +{ + const char * const list_names[] = {name}; + + return rte_metrics_reg_names(list_names, 1); +} + +int +rte_metrics_reg_names(const char * const *names, uint16_t cnt_names) +{ + struct rte_metrics_meta_s *entry; + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + uint16_t idx_name; + uint16_t idx_base; + + /* Some sanity checks */ + if (cnt_names < 1 || names == NULL) + return -EINVAL; + + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); + if (memzone == NULL) + return -EIO; + stats = memzone->addr; + + if (stats->cnt_stats + cnt_names >= RTE_METRICS_MAX_METRICS) + return -ENOMEM; + + rte_spinlock_lock(&stats->lock); + + /* Overwritten later if this is actually first set.. */ + stats->metadata[stats->idx_last_set].idx_next_set = stats->cnt_stats; + + stats->idx_last_set = idx_base = stats->cnt_stats; + + for (idx_name = 0; idx_name < cnt_names; idx_name++) { + entry = &stats->metadata[idx_name + stats->cnt_stats]; + strncpy(entry->name, names[idx_name], + RTE_METRICS_MAX_NAME_LEN); + memset(entry->value, 0, sizeof(entry->value)); + entry->idx_next_stat = idx_name + stats->cnt_stats + 1; + } + entry->idx_next_stat = 0; + entry->idx_next_set = 0; + stats->cnt_stats += cnt_names; + + rte_spinlock_unlock(&stats->lock); + + return idx_base; +} + +int +rte_metrics_update_value(int port_id, uint16_t key, const uint64_t value) +{ + return rte_metrics_update_values(port_id, key, &value, 1); +} + +int +rte_metrics_update_values(int port_id, + uint16_t key, + const uint64_t *values, + uint32_t count) +{ + struct rte_metrics_meta_s *entry; + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + uint16_t idx_metric; + uint16_t idx_value; + uint16_t cnt_setsize; + + if (port_id != RTE_METRICS_GLOBAL && + (port_id < 0 || port_id > RTE_MAX_ETHPORTS)) + return -EINVAL; + + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); + if (memzone == NULL) + return -EIO; + stats = memzone->addr; + + rte_spinlock_lock(&stats->lock); + idx_metric = key; + cnt_setsize = 1; + while (idx_metric < stats->cnt_stats) { + entry = &stats->metadata[idx_metric]; + if (entry->idx_next_stat == 0) + break; + cnt_setsize++; + idx_metric++; + } + /* Check update does not cross set border */ + if (count > cnt_setsize) { + rte_spinlock_unlock(&stats->lock); + return -ERANGE; + } + + if (port_id == RTE_METRICS_GLOBAL) + for (idx_value = 0; idx_value < count; idx_value++) { + idx_metric = key + idx_value; + stats->metadata[idx_metric].nonport_value = + values[idx_value]; + } + else + for (idx_value = 0; idx_value < count; idx_value++) { + idx_metric = key + idx_value; + stats->metadata[idx_metric].value[port_id] = + values[idx_value]; + } + rte_spinlock_unlock(&stats->lock); + return 0; +} + +int +rte_metrics_get_names(struct rte_metric_name *names, + uint16_t capacity) +{ + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + uint16_t idx_name; + int return_value; + + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); + /* If not allocated, fail silently */ + if (memzone == NULL) + return 0; + + stats = memzone->addr; + rte_spinlock_lock(&stats->lock); + if (names != NULL) { + if (capacity < stats->cnt_stats) { + return_value = stats->cnt_stats; + rte_spinlock_unlock(&stats->lock); + return return_value; + } + for (idx_name = 0; idx_name < stats->cnt_stats; idx_name++) + strncpy(names[idx_name].name, + stats->metadata[idx_name].name, + RTE_METRICS_MAX_NAME_LEN); + } + return_value = stats->cnt_stats; + rte_spinlock_unlock(&stats->lock); + return return_value; +} + +int +rte_metrics_get_values(int port_id, + struct rte_metric_value *values, + uint16_t capacity) +{ + struct rte_metrics_meta_s *entry; + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + uint16_t idx_name; + int return_value; + + if (port_id != RTE_METRICS_GLOBAL && + (port_id < 0 || port_id > RTE_MAX_ETHPORTS)) + return -EINVAL; + + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); + /* If not allocated, fail silently */ + if (memzone == NULL) + return 0; + stats = memzone->addr; + rte_spinlock_lock(&stats->lock); + + if (values != NULL) { + if (capacity < stats->cnt_stats) { + return_value = stats->cnt_stats; + rte_spinlock_unlock(&stats->lock); + return return_value; + } + if (port_id == RTE_METRICS_GLOBAL) + for (idx_name = 0; + idx_name < stats->cnt_stats; + idx_name++) { + entry = &stats->metadata[idx_name]; + values[idx_name].key = idx_name; + values[idx_name].value = entry->nonport_value; + } + else + for (idx_name = 0; + idx_name < stats->cnt_stats; + idx_name++) { + entry = &stats->metadata[idx_name]; + values[idx_name].key = idx_name; + values[idx_name].value = entry->value[port_id]; + } + } + return_value = stats->cnt_stats; + rte_spinlock_unlock(&stats->lock); + return return_value; +} diff --git a/lib/librte_metrics/rte_metrics.h b/lib/librte_metrics/rte_metrics.h new file mode 100644 index 0000000..71c57c6 --- /dev/null +++ b/lib/librte_metrics/rte_metrics.h @@ -0,0 +1,240 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016-2017 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * + * DPDK Metrics module + * + * Metrics are statistics that are not generated by PMDs, and hence + * are better reported through a mechanism that is independent from + * the ethdev-based extended statistics. Providers will typically + * be other libraries and consumers will typically be applications. + * + * Metric information is populated using a push model, where producers + * update the values contained within the metric library by calling + * an update function on the relevant metrics. Consumers receive + * metric information by querying the central metric data, which is + * held in shared memory. Currently only bulk querying of metrics + * by consumers is supported. + */ + +#ifndef _RTE_METRICS_H_ +#define _RTE_METRICS_H_ + +/** Maximum length of metric name (including null-terminator) */ +#define RTE_METRICS_MAX_NAME_LEN 64 + +/** + * Global (rather than port-specific) metric special id. + * + * When used for the port_id parameter when calling + * rte_metrics_update_metric() or rte_metrics_update_metric(), + * the global metrics, which are not associated with any specific + * port (i.e. device), are updated. + */ +#define RTE_METRICS_GLOBAL -1 + + +/** + * A name-key lookup for metrics. + * + * An array of this structure is returned by rte_metrics_get_names(). + * The struct rte_metric_value references these names via their array index. + */ +struct rte_metric_name { + /** String describing metric */ + char name[RTE_METRICS_MAX_NAME_LEN]; +}; + + +/** + * Metric value structure. + * + * This structure is used by rte_metrics_get_values() to return metrics, + * which are statistics that are not generated by PMDs. It maps a name key, + * which corresponds to an index in the array returned by + * rte_metrics_get_names(). + */ +struct rte_metric_value { + /** Numeric identifier of metric. */ + uint16_t key; + /** Value for metric */ + uint64_t value; +}; + + +/** + * Initializes metric module. This function must be called from + * a primary process before metrics are used. + * + * @param socket_id + * Socket to use for shared memory allocation. + */ +void rte_metrics_init(int socket_id); + +/** + * Register a metric, making it available as a reporting parameter. + * + * Registering a metric is the way producers declare a parameter + * that they wish to be reported. Once registered, the associated + * numeric key can be obtained via rte_metrics_get_names(), which + * is required for updating said metric's value. + * + * @param name + * Metric name + * + * @return + * - Zero or positive: Success (index key of new metric) + * - -EIO: Error, unable to access metrics shared memory + * (rte_metrics_init() not called) + * - -EINVAL: Error, invalid parameters + * - -ENOMEM: Error, maximum metrics reached + */ +int rte_metrics_reg_name(const char *name); + +/** + * Register a set of metrics. + * + * This is a bulk version of rte_metrics_reg_metrics() and aside from + * handling multiple keys at once is functionally identical. + * + * @param names + * List of metric names + * + * @param cnt_names + * Number of metrics in set + * + * @return + * - Zero or positive: Success (index key of start of set) + * - -EIO: Error, unable to access metrics shared memory + * (rte_metrics_init() not called) + * - -EINVAL: Error, invalid parameters + * - -ENOMEM: Error, maximum metrics reached + */ +int rte_metrics_reg_names(const char * const *names, uint16_t cnt_names); + +/** + * Get metric name-key lookup table. + * + * @param names + * A struct rte_metric_name array of at least *capacity* in size to + * receive key names. If this is NULL, function returns the required + * number of elements for this array. + * + * @param capacity + * Size (number of elements) of struct rte_metric_name array. + * Disregarded if names is NULL. + * + * @return + * - Positive value above capacity: error, *names* is too small. + * Return value is required size. + * - Positive value equal or less than capacity: Success. Return + * value is number of elements filled in. + * - Negative value: error. + */ +int rte_metrics_get_names( + struct rte_metric_name *names, + uint16_t capacity); + +/** + * Get metric value table. + * + * @param port_id + * Port id to query + * + * @param values + * A struct rte_metric_value array of at least *capacity* in size to + * receive metric ids and values. If this is NULL, function returns + * the required number of elements for this array. + * + * @param capacity + * Size (number of elements) of struct rte_metric_value array. + * Disregarded if names is NULL. + * + * @return + * - Positive value above capacity: error, *values* is too small. + * Return value is required size. + * - Positive value equal or less than capacity: Success. Return + * value is number of elements filled in. + * - Negative value: error. + */ +int rte_metrics_get_values( + int port_id, + struct rte_metric_value *values, + uint16_t capacity); + +/** + * Updates a metric + * + * @param port_id + * Port to update metrics for + * @param key + * Id of metric to update + * @param value + * New value + * + * @return + * - -EIO if unable to access shared metrics memory + * - Zero on success + */ +int rte_metrics_update_value( + int port_id, + uint16_t key, + const uint64_t value); + +/** + * Updates a metric set. Note that it is an error to try to + * update across a set boundary. + * + * @param port_id + * Port to update metrics for + * @param key + * Base id of metrics set to update + * @param values + * Set of new values + * @param count + * Number of new values + * + * @return + * - -ERANGE if count exceeds metric set size + * - -EIO if upable to access shared metrics memory + * - Zero on success + */ +int rte_metrics_update_values( + int port_id, + uint16_t key, + const uint64_t *values, + uint32_t count); + +#endif diff --git a/lib/librte_metrics/rte_metrics_version.map b/lib/librte_metrics/rte_metrics_version.map new file mode 100644 index 0000000..ee28fa0 --- /dev/null +++ b/lib/librte_metrics/rte_metrics_version.map @@ -0,0 +1,13 @@ +DPDK_17.02 { + global: + + rte_metrics_get_names; + rte_metrics_get_values; + rte_metrics_init; + rte_metrics_reg_name; + rte_metrics_reg_names; + rte_metrics_update_value; + rte_metrics_update_values; + + local: *; +}; diff --git a/mk/rte.app.mk b/mk/rte.app.mk index 0d0a970..46de3d3 100644 --- a/mk/rte.app.mk +++ b/mk/rte.app.mk @@ -99,6 +99,8 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL) += -lrte_eal _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE) += -lrte_cmdline _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE) += -lrte_cfgfile _LDLIBS-$(CONFIG_RTE_LIBRTE_REORDER) += -lrte_reorder +_LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS) += -lrte_metrics + _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += -lrte_pmd_bond _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += -lrte_pmd_xenvirt -lxenstore -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v10 2/7] app/proc_info: add metrics displaying 2017-02-03 10:33 ` [dpdk-dev] [PATCH v10 0/7] Expanded statistics reporting Remy Horton 2017-02-03 10:33 ` [dpdk-dev] [PATCH v10 1/7] lib: add information metrics library Remy Horton @ 2017-02-03 10:33 ` Remy Horton 2017-02-03 10:33 ` [dpdk-dev] [PATCH v10 3/7] lib: add bitrate statistics library Remy Horton ` (6 subsequent siblings) 8 siblings, 0 replies; 115+ messages in thread From: Remy Horton @ 2017-02-03 10:33 UTC (permalink / raw) To: dev; +Cc: Reshma Pattan, Thomas Monjalon From: Reshma Pattan <reshma.pattan@intel.com> Modify the dpdk-procinfo process to display the newly added metrics. Added new command line option "--metrics" to display metrics. Signed-off-by: Reshma Pattan <reshma.pattan@intel.com> Signed-off-by: Remy Horton <remy.horton@intel.com> --- app/proc_info/main.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 78 insertions(+), 1 deletion(-) diff --git a/app/proc_info/main.c b/app/proc_info/main.c index 2c56d10..f513669 100644 --- a/app/proc_info/main.c +++ b/app/proc_info/main.c @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2010-2016 Intel Corporation. All rights reserved. + * Copyright(c) 2010-2017 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -57,6 +57,7 @@ #include <rte_atomic.h> #include <rte_branch_prediction.h> #include <rte_string_fns.h> +#include <rte_metrics.h> /* Maximum long option length for option parsing. */ #define MAX_LONG_OPT_SZ 64 @@ -68,6 +69,8 @@ static uint32_t enabled_port_mask; static uint32_t enable_stats; /**< Enable xstats. */ static uint32_t enable_xstats; +/**< Enable metrics. */ +static uint32_t enable_metrics; /**< Enable stats reset. */ static uint32_t reset_stats; /**< Enable xstats reset. */ @@ -85,6 +88,8 @@ proc_info_usage(const char *prgname) " --stats: to display port statistics, enabled by default\n" " --xstats: to display extended port statistics, disabled by " "default\n" + " --metrics: to display derived metrics of the ports, disabled by " + "default\n" " --stats-reset: to reset port statistics\n" " --xstats-reset: to reset port extended statistics\n", prgname); @@ -127,6 +132,7 @@ proc_info_parse_args(int argc, char **argv) {"stats", 0, NULL, 0}, {"stats-reset", 0, NULL, 0}, {"xstats", 0, NULL, 0}, + {"metrics", 0, NULL, 0}, {"xstats-reset", 0, NULL, 0}, {NULL, 0, 0, 0} }; @@ -159,6 +165,10 @@ proc_info_parse_args(int argc, char **argv) else if (!strncmp(long_option[option_index].name, "xstats", MAX_LONG_OPT_SZ)) enable_xstats = 1; + else if (!strncmp(long_option[option_index].name, + "metrics", + MAX_LONG_OPT_SZ)) + enable_metrics = 1; /* Reset stats */ if (!strncmp(long_option[option_index].name, "stats-reset", MAX_LONG_OPT_SZ)) @@ -301,6 +311,67 @@ nic_xstats_clear(uint8_t port_id) printf("\n NIC extended statistics for port %d cleared\n", port_id); } +static void +metrics_display(int port_id) +{ + struct rte_metric_value *metrics; + struct rte_metric_name *names; + int len, ret; + static const char *nic_stats_border = "########################"; + + len = rte_metrics_get_names(NULL, 0); + if (len < 0) { + printf("Cannot get metrics count\n"); + return; + } + if (len == 0) { + printf("No metrics to display (none have been registered)\n"); + return; + } + + metrics = rte_malloc("proc_info_metrics", + sizeof(struct rte_metric_value) * len, 0); + if (metrics == NULL) { + printf("Cannot allocate memory for metrics\n"); + return; + } + + names = rte_malloc(NULL, sizeof(struct rte_metric_name) * len, 0); + if (names == NULL) { + printf("Cannot allocate memory for metrcis names\n"); + rte_free(metrics); + return; + } + + if (len != rte_metrics_get_names(names, len)) { + printf("Cannot get metrics names\n"); + rte_free(metrics); + rte_free(names); + return; + } + + if (port_id == RTE_METRICS_GLOBAL) + printf("###### Non port specific metrics #########\n"); + else + printf("###### metrics for port %-2d #########\n", port_id); + printf("%s############################\n", nic_stats_border); + ret = rte_metrics_get_values(port_id, metrics, len); + if (ret < 0 || ret > len) { + printf("Cannot get metrics values\n"); + rte_free(metrics); + rte_free(names); + return; + } + + int i; + for (i = 0; i < len; i++) + printf("%s: %"PRIu64"\n", names[i].name, metrics[i].value); + + printf("%s############################\n", nic_stats_border); + rte_free(metrics); + rte_free(names); +} + int main(int argc, char **argv) { @@ -360,8 +431,14 @@ main(int argc, char **argv) nic_stats_clear(i); else if (reset_xstats) nic_xstats_clear(i); + else if (enable_metrics) + metrics_display(i); } } + /* print port independent stats */ + if (enable_metrics) + metrics_display(RTE_METRICS_GLOBAL); + return 0; } -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v10 3/7] lib: add bitrate statistics library 2017-02-03 10:33 ` [dpdk-dev] [PATCH v10 0/7] Expanded statistics reporting Remy Horton 2017-02-03 10:33 ` [dpdk-dev] [PATCH v10 1/7] lib: add information metrics library Remy Horton 2017-02-03 10:33 ` [dpdk-dev] [PATCH v10 2/7] app/proc_info: add metrics displaying Remy Horton @ 2017-02-03 10:33 ` Remy Horton 2017-02-03 10:33 ` [dpdk-dev] [PATCH v10 4/7] app/test-pmd: add bitrate statistics calculation Remy Horton ` (5 subsequent siblings) 8 siblings, 0 replies; 115+ messages in thread From: Remy Horton @ 2017-02-03 10:33 UTC (permalink / raw) To: dev; +Cc: Thomas Monjalon This patch adds a library that calculates peak and average data-rate statistics. For ethernet devices. These statistics are reported using the metrics library. Signed-off-by: Remy Horton <remy.horton@intel.com> --- MAINTAINERS | 4 + config/common_base | 5 + doc/api/doxy-api-index.md | 1 + doc/api/doxy-api.conf | 1 + doc/guides/prog_guide/metrics_lib.rst | 63 ++++++++++ doc/guides/rel_notes/release_17_02.rst | 6 + lib/Makefile | 1 + lib/librte_bitratestats/Makefile | 53 +++++++++ lib/librte_bitratestats/rte_bitrate.c | 132 +++++++++++++++++++++ lib/librte_bitratestats/rte_bitrate.h | 80 +++++++++++++ .../rte_bitratestats_version.map | 9 ++ mk/rte.app.mk | 1 + 12 files changed, 356 insertions(+) create mode 100644 lib/librte_bitratestats/Makefile create mode 100644 lib/librte_bitratestats/rte_bitrate.c create mode 100644 lib/librte_bitratestats/rte_bitrate.h create mode 100644 lib/librte_bitratestats/rte_bitratestats_version.map diff --git a/MAINTAINERS b/MAINTAINERS index eceebaa..375adc9 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -631,6 +631,10 @@ Metrics M: Remy Horton <remy.horton@intel.com> F: lib/librte_metrics/ +Bit-rate statistica +M: Remy Horton <remy.horton@intel.com> +F: lib/librte_bitratestats/ + Test Applications ----------------- diff --git a/config/common_base b/config/common_base index b819932..e7b0e5c 100644 --- a/config/common_base +++ b/config/common_base @@ -633,3 +633,8 @@ CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n # Compile the crypto performance application # CONFIG_RTE_APP_CRYPTO_PERF=y + +# +# Compile the bitrate statistics library +# +CONFIG_RTE_LIBRTE_BITRATE=y diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md index 26a26b7..8492bce 100644 --- a/doc/api/doxy-api-index.md +++ b/doc/api/doxy-api-index.md @@ -157,4 +157,5 @@ There are many libraries, so their headers may be grouped by topics: [ABI compat] (@ref rte_compat.h), [keepalive] (@ref rte_keepalive.h), [device metrics] (@ref rte_metrics.h), + [bitrate statistics] (@ref rte_bitrate.h), [version] (@ref rte_version.h) diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf index e2e070f..4010340 100644 --- a/doc/api/doxy-api.conf +++ b/doc/api/doxy-api.conf @@ -37,6 +37,7 @@ INPUT = doc/api/doxy-api-index.md \ lib/librte_eal/common/include \ lib/librte_eal/common/include/generic \ lib/librte_acl \ + lib/librte_bitratestats \ lib/librte_cfgfile \ lib/librte_cmdline \ lib/librte_compat \ diff --git a/doc/guides/prog_guide/metrics_lib.rst b/doc/guides/prog_guide/metrics_lib.rst index 87f806d..c06023c 100644 --- a/doc/guides/prog_guide/metrics_lib.rst +++ b/doc/guides/prog_guide/metrics_lib.rst @@ -178,3 +178,66 @@ print out all metrics for a given port: free(metrics); free(names); } + + +Bit-rate statistics library +--------------------------- + +The bit-rate library calculates the exponentially-weighted moving +average and peak bit-rates for each active port (i.e. network device). +These statistics are reported via the metrics library using the +following names: + + - ``mean_bits_in``: Average inbound bit-rate + - ``mean_bits_out``: Average outbound bit-rate + - ``peak_bits_in``: Peak inbound bit-rate + - ``peak_bits_out``: Peak outbound bit-rate + +Once initialised and clocked at the appropriate frequency, these +statistics can be obtained by querying the metrics library. + +Initialization +~~~~~~~~~~~~~~ + +Before it is used the bit-rate statistics library has to be initialised +by calling ``rte_stats_bitrate_create()``, which will return a bit-rate +calculation object. Since the bit-rate library uses the metrics library +to report the calculated statistics, the bit-rate library then needs to +register the calculated statistics with the metrics library. This is +done using the helper function ``rte_stats_bitrate_reg()``. + +.. code-block:: c + + struct rte_stats_bitrates *bitrate_data; + + bitrate_data = rte_stats_bitrate_create(); + if (bitrate_data == NULL) + rte_exit(EXIT_FAILURE, "Could not allocate bit-rate data.\n"); + rte_stats_bitrate_reg(bitrate_data); + +Controlling the sampling rate +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Since the library works by periodic sampling but does not use an +internal thread, the application has to periodically call +``rte_stats_bitrate_calc()``. The frequency at which this function +is called should be the intended sampling rate required for the +calculated statistics. For instance if per-second statistics are +desired, this function should be called once a second. + +.. code-block:: c + + tics_datum = rte_rdtsc(); + tics_per_1sec = rte_get_timer_hz(); + + while( 1 ) { + /* ... */ + tics_current = rte_rdtsc(); + if (tics_current - tics_datum >= tics_per_1sec) { + /* Periodic bitrate calculation */ + for (idx_port = 0; idx_port < cnt_ports; idx_port++) + rte_stats_bitrate_calc(bitrate_data, idx_port); + tics_datum = tics_current; + } + /* ... */ + } diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst index 68581e4..98729e8 100644 --- a/doc/guides/rel_notes/release_17_02.rst +++ b/doc/guides/rel_notes/release_17_02.rst @@ -46,6 +46,11 @@ New Features reporting mechanism that is independent of other libraries such as ethdev. +* **Added bit-rate calculation library.** + + A library that can be used to calculate device bit-rates. Calculated + bitrates are reported using the metrics library. + * **Added generic EAL API for I/O device memory read/write operations.** This API introduces 8-bit, 16-bit, 32bit, 64bit I/O device @@ -348,6 +353,7 @@ The libraries prepended with a plus sign were incremented in this version. .. code-block:: diff librte_acl.so.2 + + librte_bitratestats.so.1 librte_cfgfile.so.2 librte_cmdline.so.2 librte_cryptodev.so.2 diff --git a/lib/Makefile b/lib/Makefile index 29f6a81..ecc54c0 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -50,6 +50,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_NET) += librte_net DIRS-$(CONFIG_RTE_LIBRTE_IP_FRAG) += librte_ip_frag DIRS-$(CONFIG_RTE_LIBRTE_JOBSTATS) += librte_jobstats DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics +DIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += librte_bitratestats DIRS-$(CONFIG_RTE_LIBRTE_POWER) += librte_power DIRS-$(CONFIG_RTE_LIBRTE_METER) += librte_meter DIRS-$(CONFIG_RTE_LIBRTE_SCHED) += librte_sched diff --git a/lib/librte_bitratestats/Makefile b/lib/librte_bitratestats/Makefile new file mode 100644 index 0000000..743b62c --- /dev/null +++ b/lib/librte_bitratestats/Makefile @@ -0,0 +1,53 @@ +# BSD LICENSE +# +# Copyright(c) 2016-2017 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +include $(RTE_SDK)/mk/rte.vars.mk + +# library name +LIB = librte_bitratestats.a + +CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) + +EXPORT_MAP := rte_bitratestats_version.map + +LIBABIVER := 1 + +# all source are stored in SRCS-y +SRCS-$(CONFIG_RTE_LIBRTE_BITRATE) := rte_bitrate.c + +# Install header file +SYMLINK-$(CONFIG_RTE_LIBRTE_BITRATE)-include += rte_bitrate.h + +DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_eal +DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_ether +DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_metrics + +include $(RTE_SDK)/mk/rte.lib.mk diff --git a/lib/librte_bitratestats/rte_bitrate.c b/lib/librte_bitratestats/rte_bitrate.c new file mode 100644 index 0000000..2c20272 --- /dev/null +++ b/lib/librte_bitratestats/rte_bitrate.c @@ -0,0 +1,132 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016-2017 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <rte_common.h> +#include <rte_ethdev.h> +#include <rte_malloc.h> +#include <rte_metrics.h> +#include <rte_bitrate.h> + +/* + * Persistent bit-rate data. + * @internal + */ +struct rte_stats_bitrate { + uint64_t last_ibytes; + uint64_t last_obytes; + uint64_t peak_ibits; + uint64_t peak_obits; + uint64_t ewma_ibits; + uint64_t ewma_obits; +}; + +struct rte_stats_bitrates { + struct rte_stats_bitrate port_stats[RTE_MAX_ETHPORTS]; + uint16_t id_stats_set; +}; + +struct rte_stats_bitrates * +rte_stats_bitrate_create(void) +{ + return rte_zmalloc(NULL, sizeof(struct rte_stats_bitrates), + RTE_CACHE_LINE_SIZE); +} + +int +rte_stats_bitrate_reg(struct rte_stats_bitrates *bitrate_data) +{ + const char * const names[] = { + "mean_bits_in", "mean_bits_out", + "peak_bits_in", "peak_bits_out", + }; + int return_value; + + return_value = rte_metrics_reg_names(&names[0], 4); + if (return_value >= 0) + bitrate_data->id_stats_set = return_value; + return return_value; +} + +int +rte_stats_bitrate_calc(struct rte_stats_bitrates *bitrate_data, + uint8_t port_id) +{ + struct rte_stats_bitrate *port_data; + struct rte_eth_stats eth_stats; + int ret_code; + uint64_t cnt_bits; + int64_t delta; + const int64_t alpha_percent = 20; + uint64_t values[4]; + + ret_code = rte_eth_stats_get(port_id, ð_stats); + if (ret_code != 0) + return ret_code; + + port_data = &bitrate_data->port_stats[port_id]; + + /* Incoming bitrate. This is an iteratively calculated EWMA + * (Expomentially Weighted Moving Average) that uses a + * weighting factor of alpha_percent. + */ + cnt_bits = (eth_stats.ibytes - port_data->last_ibytes) << 3; + port_data->last_ibytes = eth_stats.ibytes; + if (cnt_bits > port_data->peak_ibits) + port_data->peak_ibits = cnt_bits; + delta = cnt_bits; + delta -= port_data->ewma_ibits; + /* The +-50 fixes integer rounding during divison */ + if (delta > 0) + delta = (delta * alpha_percent + 50) / 100; + else + delta = (delta * alpha_percent - 50) / 100; + port_data->ewma_ibits += delta; + + /* Outgoing bitrate (also EWMA) */ + cnt_bits = (eth_stats.obytes - port_data->last_obytes) << 3; + port_data->last_obytes = eth_stats.obytes; + if (cnt_bits > port_data->peak_obits) + port_data->peak_obits = cnt_bits; + delta = cnt_bits; + delta -= port_data->ewma_obits; + delta = (delta * alpha_percent + 50) / 100; + port_data->ewma_obits += delta; + + values[0] = port_data->ewma_ibits; + values[1] = port_data->ewma_obits; + values[2] = port_data->peak_ibits; + values[3] = port_data->peak_obits; + rte_metrics_update_values(port_id, bitrate_data->id_stats_set, + values, 4); + return 0; +} diff --git a/lib/librte_bitratestats/rte_bitrate.h b/lib/librte_bitratestats/rte_bitrate.h new file mode 100644 index 0000000..564e4f7 --- /dev/null +++ b/lib/librte_bitratestats/rte_bitrate.h @@ -0,0 +1,80 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016-2017 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +/** + * Bitrate statistics data structure. + * This data structure is intentionally opaque. + */ +struct rte_stats_bitrates; + + +/** + * Allocate a bitrate statistics structure + * + * @return + * - Pointer to structure on success + * - NULL on error (zmalloc failure) + */ +struct rte_stats_bitrates *rte_stats_bitrate_create(void); + + +/** + * Register bitrate statistics with the metric library. + * + * @param bitrate_data + * Pointer allocated by rte_stats_create() + * + * @return + * Zero on success + * Negative on error + */ +int rte_stats_bitrate_reg(struct rte_stats_bitrates *bitrate_data); + + +/** + * Calculate statistics for current time window. The period with which + * this function is called should be the intended sampling window width. + * + * @param bitrate_data + * Bitrate statistics data pointer + * + * @param port_id + * Port id to calculate statistics for + * + * @return + * - Zero on success + * - Negative value on error + */ +int rte_stats_bitrate_calc(struct rte_stats_bitrates *bitrate_data, + uint8_t port_id); diff --git a/lib/librte_bitratestats/rte_bitratestats_version.map b/lib/librte_bitratestats/rte_bitratestats_version.map new file mode 100644 index 0000000..66f232f --- /dev/null +++ b/lib/librte_bitratestats/rte_bitratestats_version.map @@ -0,0 +1,9 @@ +DPDK_17.02 { + global: + + rte_stats_bitrate_calc; + rte_stats_bitrate_create; + rte_stats_bitrate_reg; + + local: *; +}; diff --git a/mk/rte.app.mk b/mk/rte.app.mk index 46de3d3..8f1f8d7 100644 --- a/mk/rte.app.mk +++ b/mk/rte.app.mk @@ -100,6 +100,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE) += -lrte_cmdline _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE) += -lrte_cfgfile _LDLIBS-$(CONFIG_RTE_LIBRTE_REORDER) += -lrte_reorder _LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS) += -lrte_metrics +_LDLIBS-$(CONFIG_RTE_LIBRTE_BITRATE) += -lrte_bitratestats _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += -lrte_pmd_bond -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v10 4/7] app/test-pmd: add bitrate statistics calculation 2017-02-03 10:33 ` [dpdk-dev] [PATCH v10 0/7] Expanded statistics reporting Remy Horton ` (2 preceding siblings ...) 2017-02-03 10:33 ` [dpdk-dev] [PATCH v10 3/7] lib: add bitrate statistics library Remy Horton @ 2017-02-03 10:33 ` Remy Horton 2017-02-03 10:33 ` [dpdk-dev] [PATCH v10 5/7] mbuf: add a timestamp to the mbuf for latencystats Remy Horton ` (4 subsequent siblings) 8 siblings, 0 replies; 115+ messages in thread From: Remy Horton @ 2017-02-03 10:33 UTC (permalink / raw) To: dev; +Cc: Thomas Monjalon Calculate bitrate statistics using the bitrate stats library. The resulting statistics can be viewed via proc_info. Signed-off-by: Remy Horton <remy.horton@intel.com> --- app/test-pmd/testpmd.c | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c index bfb2f8e..b31a300 100644 --- a/app/test-pmd/testpmd.c +++ b/app/test-pmd/testpmd.c @@ -1,7 +1,7 @@ /*- * BSD LICENSE * - * Copyright(c) 2010-2016 Intel Corporation. All rights reserved. + * Copyright(c) 2010-2017 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -79,6 +79,10 @@ #include <rte_pdump.h> #endif #include <rte_flow.h> +#include <rte_metrics.h> +#ifdef RTE_LIBRTE_BITRATE +#include <rte_bitrate.h> +#endif #include "testpmd.h" @@ -323,6 +327,9 @@ uint16_t nb_rx_queue_stats_mappings = 0; unsigned max_socket = 0; +/* Bitrate statistics */ +struct rte_stats_bitrates *bitrate_data; + /* Forward function declarations */ static void map_port_queue_stats_mapping_registers(uint8_t pi, struct rte_port *port); static void check_all_ports_link_status(uint32_t port_mask); @@ -922,12 +929,32 @@ run_pkt_fwd_on_lcore(struct fwd_lcore *fc, packet_fwd_t pkt_fwd) struct fwd_stream **fsm; streamid_t nb_fs; streamid_t sm_id; +#ifdef RTE_LIBRTE_BITRATE + uint64_t tics_per_1sec; + uint64_t tics_datum; + uint64_t tics_current; + uint8_t idx_port, cnt_ports; +#endif +#ifdef RTE_LIBRTE_BITRATE + cnt_ports = rte_eth_dev_count(); + tics_datum = rte_rdtsc(); + tics_per_1sec = rte_get_timer_hz(); +#endif fsm = &fwd_streams[fc->stream_idx]; nb_fs = fc->stream_nb; do { for (sm_id = 0; sm_id < nb_fs; sm_id++) (*pkt_fwd)(fsm[sm_id]); +#ifdef RTE_LIBRTE_BITRATE + tics_current = rte_rdtsc(); + if (tics_current - tics_datum >= tics_per_1sec) { + /* Periodic bitrate calculation */ + for (idx_port = 0; idx_port < cnt_ports; idx_port++) + rte_stats_bitrate_calc(bitrate_data, idx_port); + tics_datum = tics_current; + } +#endif } while (! fc->stopped); } @@ -2139,6 +2166,18 @@ main(int argc, char** argv) FOREACH_PORT(port_id, ports) rte_eth_promiscuous_enable(port_id); + /* Init metrics library */ + rte_metrics_init(rte_socket_id()); + + /* Setup bitrate stats */ +#ifdef RTE_LIBRTE_BITRATE + bitrate_data = rte_stats_bitrate_create(); + if (bitrate_data == NULL) + rte_exit(EXIT_FAILURE, "Could not allocate bitrate data.\n"); + rte_stats_bitrate_reg(bitrate_data); +#endif + + #ifdef RTE_LIBRTE_CMDLINE if (interactive == 1) { if (auto_start) { -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v10 5/7] mbuf: add a timestamp to the mbuf for latencystats 2017-02-03 10:33 ` [dpdk-dev] [PATCH v10 0/7] Expanded statistics reporting Remy Horton ` (3 preceding siblings ...) 2017-02-03 10:33 ` [dpdk-dev] [PATCH v10 4/7] app/test-pmd: add bitrate statistics calculation Remy Horton @ 2017-02-03 10:33 ` Remy Horton 2017-02-03 10:33 ` [dpdk-dev] [PATCH v10 6/7] lib: added new library for latency stats Remy Horton ` (3 subsequent siblings) 8 siblings, 0 replies; 115+ messages in thread From: Remy Horton @ 2017-02-03 10:33 UTC (permalink / raw) To: dev; +Cc: Harry van Haaren, Thomas Monjalon, Reshma Pattan From: Harry van Haaren <harry.van.haaren@intel.com> This commit adds a uint64_t to the mbuf struct, allowing collection of latency and jitter statistics by measuring packet I/O timestamps. This change is required by the latencystats library. Signed-off-by: Reshma Pattan <reshma.pattan@intel.com> Signed-off-by: Harry van Haaren <harry.van.haaren@intel.com> --- lib/librte_mbuf/rte_mbuf.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h index 0d01167..6a8c4f6 100644 --- a/lib/librte_mbuf/rte_mbuf.h +++ b/lib/librte_mbuf/rte_mbuf.h @@ -512,6 +512,9 @@ struct rte_mbuf { /** Timesync flags for use with IEEE1588. */ uint16_t timesync; + + /** Timestamp for measuring latency. */ + uint64_t timestamp; } __rte_cache_aligned; /** -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v10 6/7] lib: added new library for latency stats 2017-02-03 10:33 ` [dpdk-dev] [PATCH v10 0/7] Expanded statistics reporting Remy Horton ` (4 preceding siblings ...) 2017-02-03 10:33 ` [dpdk-dev] [PATCH v10 5/7] mbuf: add a timestamp to the mbuf for latencystats Remy Horton @ 2017-02-03 10:33 ` Remy Horton 2017-02-03 10:33 ` [dpdk-dev] [PATCH v10 7/7] app/test-pmd: add latency statistics calculation Remy Horton ` (2 subsequent siblings) 8 siblings, 0 replies; 115+ messages in thread From: Remy Horton @ 2017-02-03 10:33 UTC (permalink / raw) To: dev; +Cc: Harry van Haaren, Thomas Monjalon, Reshma Pattan From: Harry van Haaren <harry.van.haaren@intel.com> Add a library designed to calculate latency statistics and report them to the application when queried. The library measures minimum, average and maximum latencies, and jitter in nano seconds. The current implementation supports global latency stats, i.e. per application stats. Signed-off-by: Reshma Pattan <reshma.pattan@intel.com> Signed-off-by: Remy Horton <remy.horton@intel.com> Signed-off-by: Harry van Haaren <harry.van.haaren@intel.com> --- MAINTAINERS | 4 + config/common_base | 5 + doc/api/doxy-api-index.md | 1 + doc/api/doxy-api.conf | 1 + doc/guides/prog_guide/metrics_lib.rst | 58 +++- doc/guides/rel_notes/release_17_02.rst | 5 + lib/Makefile | 1 + lib/librte_latencystats/Makefile | 56 ++++ lib/librte_latencystats/rte_latencystats.c | 366 +++++++++++++++++++++ lib/librte_latencystats/rte_latencystats.h | 154 +++++++++ .../rte_latencystats_version.map | 11 + mk/rte.app.mk | 2 +- 12 files changed, 661 insertions(+), 3 deletions(-) create mode 100644 lib/librte_latencystats/Makefile create mode 100644 lib/librte_latencystats/rte_latencystats.c create mode 100644 lib/librte_latencystats/rte_latencystats.h create mode 100644 lib/librte_latencystats/rte_latencystats_version.map diff --git a/MAINTAINERS b/MAINTAINERS index 375adc9..b89cd3a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -635,6 +635,10 @@ Bit-rate statistica M: Remy Horton <remy.horton@intel.com> F: lib/librte_bitratestats/ +Latency Stats +M: Reshma Pattan <reshma.pattan@intel.com> +F: lib/librte_latencystats/ + Test Applications ----------------- diff --git a/config/common_base b/config/common_base index e7b0e5c..ccfe1cd 100644 --- a/config/common_base +++ b/config/common_base @@ -638,3 +638,8 @@ CONFIG_RTE_APP_CRYPTO_PERF=y # Compile the bitrate statistics library # CONFIG_RTE_LIBRTE_BITRATE=y + +# +# Compile the latency statistics library +# +CONFIG_RTE_LIBRTE_LATENCY_STATS=y diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md index 8492bce..9d1818c 100644 --- a/doc/api/doxy-api-index.md +++ b/doc/api/doxy-api-index.md @@ -158,4 +158,5 @@ There are many libraries, so their headers may be grouped by topics: [keepalive] (@ref rte_keepalive.h), [device metrics] (@ref rte_metrics.h), [bitrate statistics] (@ref rte_bitrate.h), + [latency statistics] (@ref rte_latencystats.h), [version] (@ref rte_version.h) diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf index 4010340..84a4fdd 100644 --- a/doc/api/doxy-api.conf +++ b/doc/api/doxy-api.conf @@ -50,6 +50,7 @@ INPUT = doc/api/doxy-api-index.md \ lib/librte_jobstats \ lib/librte_kni \ lib/librte_kvargs \ + lib/librte_latencystats \ lib/librte_lpm \ lib/librte_mbuf \ lib/librte_mempool \ diff --git a/doc/guides/prog_guide/metrics_lib.rst b/doc/guides/prog_guide/metrics_lib.rst index c06023c..1423288 100644 --- a/doc/guides/prog_guide/metrics_lib.rst +++ b/doc/guides/prog_guide/metrics_lib.rst @@ -199,8 +199,8 @@ statistics can be obtained by querying the metrics library. Initialization ~~~~~~~~~~~~~~ -Before it is used the bit-rate statistics library has to be initialised -by calling ``rte_stats_bitrate_create()``, which will return a bit-rate +Before the library can be used, it has to be initialised by calling +``rte_stats_bitrate_create()``, which will return a bit-rate calculation object. Since the bit-rate library uses the metrics library to report the calculated statistics, the bit-rate library then needs to register the calculated statistics with the metrics library. This is @@ -241,3 +241,57 @@ desired, this function should be called once a second. } /* ... */ } + + +Latency statistics library +-------------------------- + +The latency statistics library calculates the latency of packet +processing by a DPDK application, reporting the minimum, average, +and maximum nano-seconds that packet processing takes, as well as +the jitter in processing delay. These statistics are then reported +via the metrics library using the following names: + + - ``min_latency_ns``: Minimum processing latency (nano-seconds) + - ``avg_latency_ns``: Average processing latency (nano-seconds) + - ``mac_latency_ns``: Maximum processing latency (nano-seconds) + - ``jitter_ns``: Variance in processing latency (nano-seconds) + +Once initialised and clocked at the appropriate frequency, these +statistics can be obtained by querying the metrics library. + +Initialization +~~~~~~~~~~~~~~ + +Before the library can be used, it has to be initialised by calling +``rte_latencystats_init()``. + +.. code-block:: c + + lcoreid_t latencystats_lcore_id = -1; + + int ret = rte_latencystats_init(1, NULL); + if (ret) + rte_exit(EXIT_FAILURE, "Could not allocate latency data.\n"); + + +Triggering statistic updates +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``rte_latencystats_update()`` function needs to be called +periodically so that latency statistics can be updated. + +.. code-block:: c + + if (latencystats_lcore_id == rte_lcore_id()) + rte_latencystats_update(); + +Library shutdown +~~~~~~~~~~~~~~~~ + +When finished, ``rte_latencystats_uninit()`` needs to be called to +de-initialise the latency library. + +.. code-block:: c + + rte_latencystats_uninit(); diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst index 98729e8..bb4ad93 100644 --- a/doc/guides/rel_notes/release_17_02.rst +++ b/doc/guides/rel_notes/release_17_02.rst @@ -224,6 +224,10 @@ New Features See the :ref:`Elastic Flow Distributor Library <Efd_Library>` documentation in the Programmers Guide document, for more information. +* **Added latency stats library.** + + A library that measures packet latency. The collected statistics are jitter + and latency. For latency the minimum, average, and maximum is measured. Resolved Issues --------------- @@ -365,6 +369,7 @@ The libraries prepended with a plus sign were incremented in this version. librte_jobstats.so.1 librte_kni.so.2 librte_kvargs.so.1 + + librte_latencystats.so.1 librte_lpm.so.2 librte_mbuf.so.2 librte_mempool.so.2 diff --git a/lib/Makefile b/lib/Makefile index ecc54c0..78cba3e 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -51,6 +51,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_IP_FRAG) += librte_ip_frag DIRS-$(CONFIG_RTE_LIBRTE_JOBSTATS) += librte_jobstats DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics DIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += librte_bitratestats +DIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += librte_latencystats DIRS-$(CONFIG_RTE_LIBRTE_POWER) += librte_power DIRS-$(CONFIG_RTE_LIBRTE_METER) += librte_meter DIRS-$(CONFIG_RTE_LIBRTE_SCHED) += librte_sched diff --git a/lib/librte_latencystats/Makefile b/lib/librte_latencystats/Makefile new file mode 100644 index 0000000..fd145d3 --- /dev/null +++ b/lib/librte_latencystats/Makefile @@ -0,0 +1,56 @@ +# BSD LICENSE +# +# Copyright(c) 2016-2017 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +include $(RTE_SDK)/mk/rte.vars.mk + +# library name +LIB = librte_latencystats.a + +CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3 +LDLIBS += -lm +LDLIBS += -lpthread + +EXPORT_MAP := rte_latencystats_version.map + +LIBABIVER := 1 + +# all source are stored in SRCS-y +SRCS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) := rte_latencystats.c + +# install this header file +SYMLINK-$(CONFIG_RTE_LIBRTE_LATENCY_STATS)-include := rte_latencystats.h + +# this lib depends upon: +DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_mbuf +DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_eal +DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_ether +DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_metrics + +include $(RTE_SDK)/mk/rte.lib.mk diff --git a/lib/librte_latencystats/rte_latencystats.c b/lib/librte_latencystats/rte_latencystats.c new file mode 100644 index 0000000..5334b8b --- /dev/null +++ b/lib/librte_latencystats/rte_latencystats.c @@ -0,0 +1,366 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016-2017 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <unistd.h> +#include <sys/types.h> +#include <stdbool.h> +#include <math.h> + +#include <rte_mbuf.h> +#include <rte_log.h> +#include <rte_cycles.h> +#include <rte_ethdev.h> +#include <rte_metrics.h> +#include <rte_memzone.h> +#include <rte_lcore.h> +#include <rte_timer.h> + +#include "rte_latencystats.h" + +/** Nano seconds per second */ +#define NS_PER_SEC 1E9 + +/** Clock cycles per nano second */ +static uint64_t +latencystat_cycles_per_ns(void) +{ + return rte_get_timer_hz() / NS_PER_SEC; +} + +/* Macros for printing using RTE_LOG */ +#define RTE_LOGTYPE_LATENCY_STATS RTE_LOGTYPE_USER1 + +static const char *MZ_RTE_LATENCY_STATS = "rte_latencystats"; +static int latency_stats_index; +static uint64_t samp_intvl; +static uint64_t timer_tsc; +static uint64_t prev_tsc; + +struct rte_latency_stats { + float min_latency; /**< Minimum latency in nano seconds */ + float avg_latency; /**< Average latency in nano seconds */ + float max_latency; /**< Maximum latency in nano seconds */ + float jitter; /** Latency variation */ +}; + +static struct rte_latency_stats *glob_stats; + +struct rxtx_cbs { + struct rte_eth_rxtx_callback *cb; +}; + +static struct rxtx_cbs rx_cbs[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT]; +static struct rxtx_cbs tx_cbs[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT]; + +struct latency_stats_nameoff { + char name[RTE_ETH_XSTATS_NAME_SIZE]; + unsigned int offset; +}; + +static const struct latency_stats_nameoff lat_stats_strings[] = { + {"min_latency_ns", offsetof(struct rte_latency_stats, min_latency)}, + {"avg_latency_ns", offsetof(struct rte_latency_stats, avg_latency)}, + {"max_latency_ns", offsetof(struct rte_latency_stats, max_latency)}, + {"jitter_ns", offsetof(struct rte_latency_stats, jitter)}, +}; + +#define NUM_LATENCY_STATS (sizeof(lat_stats_strings) / \ + sizeof(lat_stats_strings[0])) + +int32_t +rte_latencystats_update(void) +{ + unsigned int i; + float *stats_ptr = NULL; + uint64_t values[NUM_LATENCY_STATS] = {0}; + int ret; + + for (i = 0; i < NUM_LATENCY_STATS; i++) { + stats_ptr = RTE_PTR_ADD(glob_stats, + lat_stats_strings[i].offset); + values[i] = (uint64_t)floor((*stats_ptr)/ + latencystat_cycles_per_ns()); + } + + ret = rte_metrics_update_values(RTE_METRICS_GLOBAL, + latency_stats_index, + values, NUM_LATENCY_STATS); + if (ret < 0) + RTE_LOG(INFO, LATENCY_STATS, "Failed to push the stats\n"); + + return ret; +} + +static void +rte_latencystats_fill_values(struct rte_metric_value *values) +{ + unsigned int i; + float *stats_ptr = NULL; + + for (i = 0; i < NUM_LATENCY_STATS; i++) { + stats_ptr = RTE_PTR_ADD(glob_stats, + lat_stats_strings[i].offset); + values[i].key = i; + values[i].value = (uint64_t)floor((*stats_ptr)/ + latencystat_cycles_per_ns()); + } +} + +static uint16_t +add_time_stamps(uint8_t pid __rte_unused, + uint16_t qid __rte_unused, + struct rte_mbuf **pkts, + uint16_t nb_pkts, + uint16_t max_pkts __rte_unused, + void *user_cb __rte_unused) +{ + unsigned int i; + uint64_t diff_tsc, now; + + /* + * For every sample interval, + * time stamp is marked on one received packet. + */ + now = rte_rdtsc(); + for (i = 0; i < nb_pkts; i++) { + diff_tsc = now - prev_tsc; + timer_tsc += diff_tsc; + if (timer_tsc >= samp_intvl) { + /* + * TBD: Mark the timestamp only + * if not already marked by the + * hardware or the PMD. + */ + pkts[i]->timestamp = now; + timer_tsc = 0; + } + prev_tsc = now; + now = rte_rdtsc(); + } + + return nb_pkts; +} + +static uint16_t +calc_latency(uint8_t pid __rte_unused, + uint16_t qid __rte_unused, + struct rte_mbuf **pkts, + uint16_t nb_pkts, + void *_ __rte_unused) +{ + unsigned int i, cnt = 0; + uint64_t now; + float latency[nb_pkts]; + static float prev_latency; + /* + * Alpha represents degree of weighting decrease in EWMA, + * a constant smoothing factor between 0 and 1. The value + * is used below for measuring average latency. + */ + const float alpha = 0.2; + + now = rte_rdtsc(); + for (i = 0; i < nb_pkts; i++) { + if (pkts[i]->timestamp) + latency[cnt++] = now - pkts[i]->timestamp; + } + + for (i = 0; i < cnt; i++) { + /* + * The jitter is calculated as statistical mean of interpacket + * delay variation. The "jitter estimate" is computed by taking + * the absolute values of the ipdv sequence and applying an + * exponential filter with parameter 1/16 to generate the + * estimate. i.e J=J+(|D(i-1,i)|-J)/16. Where J is jitter, + * D(i-1,i) is difference in latency of two consecutive packets + * i-1 and i. + * Reference: Calculated as per RFC 5481, sec 4.1, + * RFC 3393 sec 4.5, RFC 1889 sec. + */ + glob_stats->jitter += (abs(prev_latency - latency[i]) + - glob_stats->jitter)/16; + if (glob_stats->min_latency == 0) + glob_stats->min_latency = latency[i]; + else if (latency[i] < glob_stats->min_latency) + glob_stats->min_latency = latency[i]; + else if (latency[i] > glob_stats->max_latency) + glob_stats->max_latency = latency[i]; + /* + * The average latency is measured using exponential moving + * average, i.e. using EWMA + * https://en.wikipedia.org/wiki/Moving_average + */ + glob_stats->avg_latency += + alpha * (latency[i] - glob_stats->avg_latency); + prev_latency = latency[i]; + } + + return nb_pkts; +} + +int +rte_latencystats_init(uint64_t app_samp_intvl, + rte_latency_stats_flow_type_fn user_cb) +{ + unsigned int i; + uint8_t pid; + uint16_t qid; + struct rxtx_cbs *cbs = NULL; + const uint8_t nb_ports = rte_eth_dev_count(); + const char *ptr_strings[NUM_LATENCY_STATS] = {0}; + const struct rte_memzone *mz = NULL; + const unsigned int flags = 0; + + if (rte_memzone_lookup(MZ_RTE_LATENCY_STATS)) + return -EEXIST; + + /** Allocate stats in shared memory fo multi process support */ + mz = rte_memzone_reserve(MZ_RTE_LATENCY_STATS, sizeof(*glob_stats), + rte_socket_id(), flags); + if (mz == NULL) { + RTE_LOG(ERR, LATENCY_STATS, "Cannot reserve memory: %s:%d\n", + __func__, __LINE__); + return -ENOMEM; + } + + glob_stats = mz->addr; + samp_intvl = app_samp_intvl * latencystat_cycles_per_ns(); + + /** Register latency stats with stats library */ + for (i = 0; i < NUM_LATENCY_STATS; i++) + ptr_strings[i] = lat_stats_strings[i].name; + + latency_stats_index = rte_metrics_reg_names(ptr_strings, + NUM_LATENCY_STATS); + if (latency_stats_index < 0) { + RTE_LOG(DEBUG, LATENCY_STATS, + "Failed to register latency stats names\n"); + return -1; + } + + /** Register Rx/Tx callbacks */ + for (pid = 0; pid < nb_ports; pid++) { + struct rte_eth_dev_info dev_info; + rte_eth_dev_info_get(pid, &dev_info); + for (qid = 0; qid < dev_info.nb_rx_queues; qid++) { + cbs = &rx_cbs[pid][qid]; + cbs->cb = rte_eth_add_first_rx_callback(pid, qid, + add_time_stamps, user_cb); + if (!cbs->cb) + RTE_LOG(INFO, LATENCY_STATS, "Failed to " + "register Rx callback for pid=%d, " + "qid=%d\n", pid, qid); + } + for (qid = 0; qid < dev_info.nb_tx_queues; qid++) { + cbs = &tx_cbs[pid][qid]; + cbs->cb = rte_eth_add_tx_callback(pid, qid, + calc_latency, user_cb); + if (!cbs->cb) + RTE_LOG(INFO, LATENCY_STATS, "Failed to " + "register Tx callback for pid=%d, " + "qid=%d\n", pid, qid); + } + } + return 0; +} + +int +rte_latencystats_uninit(void) +{ + uint8_t pid; + uint16_t qid; + int ret = 0; + struct rxtx_cbs *cbs = NULL; + const uint8_t nb_ports = rte_eth_dev_count(); + + /** De register Rx/Tx callbacks */ + for (pid = 0; pid < nb_ports; pid++) { + struct rte_eth_dev_info dev_info; + rte_eth_dev_info_get(pid, &dev_info); + for (qid = 0; qid < dev_info.nb_rx_queues; qid++) { + cbs = &rx_cbs[pid][qid]; + ret = rte_eth_remove_rx_callback(pid, qid, cbs->cb); + if (ret) + RTE_LOG(INFO, LATENCY_STATS, "failed to " + "remove Rx callback for pid=%d, " + "qid=%d\n", pid, qid); + } + for (qid = 0; qid < dev_info.nb_tx_queues; qid++) { + cbs = &tx_cbs[pid][qid]; + ret = rte_eth_remove_tx_callback(pid, qid, cbs->cb); + if (ret) + RTE_LOG(INFO, LATENCY_STATS, "failed to " + "remove Tx callback for pid=%d, " + "qid=%d\n", pid, qid); + } + } + + return 0; +} + +int +rte_latencystats_get_names(struct rte_metric_name *names, uint16_t size) +{ + unsigned int i; + + if (names == NULL || size < NUM_LATENCY_STATS) + return NUM_LATENCY_STATS; + + for (i = 0; i < NUM_LATENCY_STATS; i++) + snprintf(names[i].name, sizeof(names[i].name), + "%s", lat_stats_strings[i].name); + + return NUM_LATENCY_STATS; +} + +int +rte_latencystats_get(struct rte_metric_value *values, uint16_t size) +{ + if (size < NUM_LATENCY_STATS || values == NULL) + return NUM_LATENCY_STATS; + + if (rte_eal_process_type() == RTE_PROC_SECONDARY) { + const struct rte_memzone *mz; + mz = rte_memzone_lookup(MZ_RTE_LATENCY_STATS); + if (mz == NULL) { + RTE_LOG(ERR, LATENCY_STATS, + "Latency stats memzone not found\n"); + return -ENOMEM; + } + glob_stats = mz->addr; + } + + /* Retrieve latency stats */ + rte_latencystats_fill_values(values); + + return NUM_LATENCY_STATS; +} diff --git a/lib/librte_latencystats/rte_latencystats.h b/lib/librte_latencystats/rte_latencystats.h new file mode 100644 index 0000000..28c6dcf --- /dev/null +++ b/lib/librte_latencystats/rte_latencystats.h @@ -0,0 +1,154 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016-2017 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _RTE_LATENCYSTATS_H_ +#define _RTE_LATENCYSTATS_H_ + +/** + * @file + * RTE latency stats + * + * library to provide application and flow based latency stats. + */ + +#include <rte_metrics.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Note: This function pointer is for future flow based latency stats + * implementation. + * + * Function type used for identifting flow types of a Rx packet. + * + * The callback function is called on Rx for each packet. + * This function is used for flow based latency calculations. + * + * @param pkt + * Packet that has to be identified with its flow types. + * @param user_param + * The arbitrary user parameter passed in by the application when + * the callback was originally configured. + * @return + * The flow_mask, representing the multiple flow types of a packet. + */ +typedef uint16_t (*rte_latency_stats_flow_type_fn)(struct rte_mbuf *pkt, + void *user_param); + +/** + * Registers Rx/Tx callbacks for each active port, queue. + * + * @param samp_intvl + * Sampling time period in nano seconds, at which packet + * should be marked with time stamp. + * @param user_cb + * Note: This param is for future flow based latency stats + * implementation. + * User callback to be called to get flow types of a packet. + * Used for flow based latency calculation. + * If the value is NULL, global stats will be calculated, + * else flow based latency stats will be calculated. + * For now just pass on the NULL value to this param. + * @return + * -1 : On error + * -ENOMEM: On error + * 0 : On success + */ +int rte_latencystats_init(uint64_t samp_intvl, + rte_latency_stats_flow_type_fn user_cb); + +/** + * Calculates the latency and jitter values internally, exposing the updated + * values via *rte_latencystats_get* or the rte_metrics API. + * @return: + * 0 : on Success + * < 0 : Error in updating values. + */ +int32_t rte_latencystats_update(void); + +/** + * Removes registered Rx/Tx callbacks for each active port, queue. + * + * @return + * -1: On error + * 0: On success + */ +int rte_latencystats_uninit(void); + +/** + * Retrieve names of latency statistics + * + * @param names + * Block of memory to insert names into. Must be at least size in capacity. + * If set to NULL, function returns required capacity. + * @param size + * Capacity of latency stats names (number of names). + * @return + * - positive value lower or equal to size: success. The return value + * is the number of entries filled in the stats table. + * - positive value higher than size: error, the given statistics table + * is too small. The return value corresponds to the size that should + * be given to succeed. The entries in the table are not valid and + * shall not be used by the caller. + */ +int rte_latencystats_get_names(struct rte_metric_name *names, + uint16_t size); + +/** + * Retrieve latency statistics. + * + * @param values + * A pointer to a table of structure of type *rte_metric_value* + * to be filled with latency statistics ids and values. + * This parameter can be set to NULL if size is 0. + * @param size + * The size of the stats table, which should be large enough to store + * all the latency stats. + * @return + * - positive value lower or equal to size: success. The return value + * is the number of entries filled in the stats table. + * - positive value higher than size: error, the given statistics table + * is too small. The return value corresponds to the size that should + * be given to succeed. The entries in the table are not valid and + * shall not be used by the caller. + * -ENOMEM: On failure. + */ +int rte_latencystats_get(struct rte_metric_value *values, + uint16_t size); + +#ifdef __cplusplus +} +#endif + +#endif /* _RTE_LATENCYSTATS_H_ */ diff --git a/lib/librte_latencystats/rte_latencystats_version.map b/lib/librte_latencystats/rte_latencystats_version.map new file mode 100644 index 0000000..d240563 --- /dev/null +++ b/lib/librte_latencystats/rte_latencystats_version.map @@ -0,0 +1,11 @@ +DPDK_17.02 { + global: + + rte_latencystats_get; + rte_latencystats_get_names; + rte_latencystats_init; + rte_latencystats_uninit; + rte_latencystats_update; + + local: *; +}; diff --git a/mk/rte.app.mk b/mk/rte.app.mk index 8f1f8d7..97b680a 100644 --- a/mk/rte.app.mk +++ b/mk/rte.app.mk @@ -101,7 +101,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_CFGFILE) += -lrte_cfgfile _LDLIBS-$(CONFIG_RTE_LIBRTE_REORDER) += -lrte_reorder _LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS) += -lrte_metrics _LDLIBS-$(CONFIG_RTE_LIBRTE_BITRATE) += -lrte_bitratestats - +_LDLIBS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += -lrte_latencystats _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_BOND) += -lrte_pmd_bond _LDLIBS-$(CONFIG_RTE_LIBRTE_PMD_XENVIRT) += -lrte_pmd_xenvirt -lxenstore -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v10 7/7] app/test-pmd: add latency statistics calculation 2017-02-03 10:33 ` [dpdk-dev] [PATCH v10 0/7] Expanded statistics reporting Remy Horton ` (5 preceding siblings ...) 2017-02-03 10:33 ` [dpdk-dev] [PATCH v10 6/7] lib: added new library for latency stats Remy Horton @ 2017-02-03 10:33 ` Remy Horton 2017-02-16 10:53 ` [dpdk-dev] [PATCH v10 0/7] Expanded statistics reporting Thomas Monjalon 2017-03-09 16:25 ` [dpdk-dev] [PATCH v11 " Remy Horton 8 siblings, 0 replies; 115+ messages in thread From: Remy Horton @ 2017-02-03 10:33 UTC (permalink / raw) To: dev; +Cc: Harry van Haaren, Thomas Monjalon, Reshma Pattan From: Harry van Haaren <harry.van.haaren@intel.com> This patch adds latency stats commandline argument to testpmd, allowing to specify the lcore to use for latencystats updates. Signed-off-by: Reshma Pattan <reshma.pattan@intel.com> Signed-off-by: Harry van Haaren <harry.van.haaren@intel.com> Signed-off-by: Remy Horton <remy.horton@intel.com> --- app/test-pmd/parameters.c | 20 +++++++++++++++++++- app/test-pmd/testpmd.c | 37 +++++++++++++++++++++++++++++++++++++ app/test-pmd/testpmd.h | 6 +++++- 3 files changed, 61 insertions(+), 2 deletions(-) diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c index 28db8cd..30b60ba 100644 --- a/app/test-pmd/parameters.c +++ b/app/test-pmd/parameters.c @@ -1,7 +1,7 @@ /*- * BSD LICENSE * - * Copyright(c) 2010-2016 Intel Corporation. All rights reserved. + * Copyright(c) 2010-2017 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -149,6 +149,10 @@ usage(char* progname) "the packet will be enqueued into the rx drop-queue. " "If the drop-queue doesn't exist, the packet is dropped. " "By default drop-queue=127.\n"); +#ifdef RTE_LIBRTE_LATENCY_STATS + printf(" --latencystats=N: enable latency and jitter statistcs " + "monitoring on lcore id N.\n"); +#endif printf(" --crc-strip: enable CRC stripping by hardware.\n"); printf(" --enable-lro: enable large receive offload.\n"); printf(" --enable-rx-cksum: enable rx hardware checksum offload.\n"); @@ -526,6 +530,7 @@ launch_args_parse(int argc, char** argv) { "pkt-filter-report-hash", 1, 0, 0 }, { "pkt-filter-size", 1, 0, 0 }, { "pkt-filter-drop-queue", 1, 0, 0 }, + { "latencystats", 1, 0, 0 }, { "crc-strip", 0, 0, 0 }, { "enable-lro", 0, 0, 0 }, { "enable-rx-cksum", 0, 0, 0 }, @@ -766,6 +771,19 @@ launch_args_parse(int argc, char** argv) "drop queue %d invalid - must" "be >= 0 \n", n); } +#ifdef RTE_LIBRTE_LATENCY_STATS + if (!strcmp(lgopts[opt_idx].name, + "latencystats")) { + n = atoi(optarg); + if (n >= 0) { + latencystats_lcore_id = (lcoreid_t) n; + latencystats_enabled = 1; + } else + rte_exit(EXIT_FAILURE, + "invalid lcore id %d for latencystats" + " must be >= 0\n", n); + } +#endif if (!strcmp(lgopts[opt_idx].name, "crc-strip")) rx_mode.hw_strip_crc = 1; if (!strcmp(lgopts[opt_idx].name, "enable-lro")) diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c index b31a300..524e758 100644 --- a/app/test-pmd/testpmd.c +++ b/app/test-pmd/testpmd.c @@ -83,6 +83,10 @@ #ifdef RTE_LIBRTE_BITRATE #include <rte_bitrate.h> #endif +#include <rte_metrics.h> +#ifdef RTE_LIBRTE_LATENCY_STATS +#include <rte_latencystats.h> +#endif #include "testpmd.h" @@ -276,6 +280,20 @@ uint32_t bypass_timeout = RTE_BYPASS_TMT_OFF; #endif +#ifdef RTE_LIBRTE_LATENCY_STATS + +/* + * Set when latency stats is enabled in the commandline + */ +uint8_t latencystats_enabled; + +/* + * Lcore ID to serive latency statistics. + */ +lcoreid_t latencystats_lcore_id = -1; + +#endif + /* * Ethernet device configuration. */ @@ -955,6 +973,11 @@ run_pkt_fwd_on_lcore(struct fwd_lcore *fc, packet_fwd_t pkt_fwd) tics_datum = tics_current; } #endif +#ifdef RTE_LIBRTE_LATENCY_STATS + if (latencystats_lcore_id == rte_lcore_id()) + rte_latencystats_update(); +#endif + } while (! fc->stopped); } @@ -2108,6 +2131,9 @@ signal_handler(int signum) /* uninitialize packet capture framework */ rte_pdump_uninit(); #endif +#ifdef RTE_LIBRTE_LATENCY_STATS + rte_latencystats_uninit(); +#endif force_quit(); /* exit with the expected status */ signal(signum, SIG_DFL); @@ -2169,6 +2195,17 @@ main(int argc, char** argv) /* Init metrics library */ rte_metrics_init(rte_socket_id()); +#ifdef RTE_LIBRTE_LATENCY_STATS + if (latencystats_enabled != 0) { + int ret = rte_latencystats_init(1, NULL); + if (ret) + printf("Warning: latencystats init()" + " returned error %d\n", ret); + printf("Latencystats running on lcore %d\n", + latencystats_lcore_id); + } +#endif + /* Setup bitrate stats */ #ifdef RTE_LIBRTE_BITRATE bitrate_data = rte_stats_bitrate_create(); diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h index 8cf2860..f0652ee 100644 --- a/app/test-pmd/testpmd.h +++ b/app/test-pmd/testpmd.h @@ -1,7 +1,7 @@ /*- * BSD LICENSE * - * Copyright(c) 2010-2016 Intel Corporation. All rights reserved. + * Copyright(c) 2010-2017 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -381,6 +381,10 @@ extern enum dcb_queue_mapping_mode dcb_q_mapping; extern uint16_t mbuf_data_size; /**< Mbuf data space size. */ extern uint32_t param_total_num_mbufs; + +extern uint8_t latencystats_enabled; +extern lcoreid_t latencystats_lcore_id; + extern struct rte_fdir_conf fdir_conf; /* -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [PATCH v10 0/7] Expanded statistics reporting 2017-02-03 10:33 ` [dpdk-dev] [PATCH v10 0/7] Expanded statistics reporting Remy Horton ` (6 preceding siblings ...) 2017-02-03 10:33 ` [dpdk-dev] [PATCH v10 7/7] app/test-pmd: add latency statistics calculation Remy Horton @ 2017-02-16 10:53 ` Thomas Monjalon 2017-02-23 7:09 ` Remy Horton 2017-03-09 16:25 ` [dpdk-dev] [PATCH v11 " Remy Horton 8 siblings, 1 reply; 115+ messages in thread From: Thomas Monjalon @ 2017-02-16 10:53 UTC (permalink / raw) To: Remy Horton; +Cc: dev 2017-02-03 10:33, Remy Horton: > This patchset extends statistics reporting to include peak and > average data-rate metrics. It comes in two parts: a statistics > reporting library, and a bitrate calculation library that uses > it. This structure is intended to seperate statistic reporting > from ethdev and allow more flexible metric registration. Note that this series integrates a third part for latency metric. > v10 changes: > * Rebased > * Relocated some config-related directives. > * Removed incorrect capitalisations in API docs. > * Formatting & detail corrections in release notes. > * Moved around struct member descriptions. > * Rewritten rte_metrics.h file description. > * Rewritten description of RTE_METRICS_GLOBAL. > * Used 'producers' and 'consumers' as terms. > * Removed markup (bold text) in Doxygen tags. > * Added programming guide section. Thanks for adding the prog guide section. It helps. I think there are three remaining questions: - When the metrics computation are done? (in which thread?) - May the few lines of computation code be done differently when tightly integrated in an application logic? - Could it be hosted in a separate repository on dpdk.org? ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [PATCH v10 0/7] Expanded statistics reporting 2017-02-16 10:53 ` [dpdk-dev] [PATCH v10 0/7] Expanded statistics reporting Thomas Monjalon @ 2017-02-23 7:09 ` Remy Horton 2017-02-23 8:45 ` Thomas Monjalon 0 siblings, 1 reply; 115+ messages in thread From: Remy Horton @ 2017-02-23 7:09 UTC (permalink / raw) To: Thomas Monjalon; +Cc: dev On 16/02/2017 10:53, Thomas Monjalon wrote: > 2017-02-03 10:33, Remy Horton: [..] > I think there are three remaining questions: > - When the metrics computation are done? (in which thread?) Actual calculation is not done by libmetrics itself - it only handles distribution. Calculation is done prior to the calculated values being passed to rte_metrics_update_value*(), so the thread that does the calculation is a decision for the application. > - May the few lines of computation code be done differently when tightly > integrated in an application logic? Yes, since it is the application itself (or in the case of bit-rate, a separate library) that does the calculation. > - Could it be hosted in a separate repository on dpdk.org? > That's part of a broader discussion on how DPDK is packaged. ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [PATCH v10 0/7] Expanded statistics reporting 2017-02-23 7:09 ` Remy Horton @ 2017-02-23 8:45 ` Thomas Monjalon 0 siblings, 0 replies; 115+ messages in thread From: Thomas Monjalon @ 2017-02-23 8:45 UTC (permalink / raw) To: Remy Horton; +Cc: dev 2017-02-23 07:09, Remy Horton: > > On 16/02/2017 10:53, Thomas Monjalon wrote: > > 2017-02-03 10:33, Remy Horton: > [..] > > I think there are three remaining questions: > > - When the metrics computation are done? (in which thread?) > > Actual calculation is not done by libmetrics itself - it only handles > distribution. Calculation is done prior to the calculated values being > passed to rte_metrics_update_value*(), so the thread that does the > calculation is a decision for the application. Of course computation is not done in libmetrics. The question was about its integration in the application and the perfromance impact. Should it be in the dataplane threads or in separate threads? > > - May the few lines of computation code be done differently when tightly > > integrated in an application logic? > > Yes, since it is the application itself (or in the case of bit-rate, a > separate library) that does the calculation. The question was more about the cache misses with this library. > > - Could it be hosted in a separate repository on dpdk.org? > > That's part of a broader discussion on how DPDK is packaged. And specifically for these metrics libraries, do you agree it could be packaged separately? ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v11 0/7] Expanded statistics reporting 2017-02-03 10:33 ` [dpdk-dev] [PATCH v10 0/7] Expanded statistics reporting Remy Horton ` (7 preceding siblings ...) 2017-02-16 10:53 ` [dpdk-dev] [PATCH v10 0/7] Expanded statistics reporting Thomas Monjalon @ 2017-03-09 16:25 ` Remy Horton 2017-03-09 16:25 ` [dpdk-dev] [PATCH v11 1/7] lib: add information metrics library Remy Horton ` (6 more replies) 8 siblings, 7 replies; 115+ messages in thread From: Remy Horton @ 2017-03-09 16:25 UTC (permalink / raw) To: dev; +Cc: Thomas Monjalon This patchset consists of three libraries: A Metrics library for distributing device information, a library that calculates bit-rate statistics, and a library that calculates latency statistics. The latter two libraries make use of the first library. Metrics Library --------------- The Metrics library implements a mechanism by which producers can publish numeric information for later querying by consumers. In practice producers will typically be other libraries or primary processes, whereas consumers will typically be applications. Metrics themselves are statistics that are not generated by PMDs. Metric information is populated using a push model, where producers update the values contained within the metric library by calling an update function on the relevant metrics. Consumers receive metric information by querying the central metric data, which is held in shared memory so it can also be accessed by secondary processes. For each metric, a separate value is maintained for each port id, and when publishing metric values the producers need to specify which port is being updated. In addition there is a special id RTE_METRICS_GLOBAL that is intended for global statistics that are not associated with any individual device. Since the metrics library is self-contained, the only restriction on port numbers is that they are less than RTE_MAX_ETHPORTS - there is no requirement for the ports to actually exist. Metrics must first be registered, which is the way producers declare the names of the metrics they will be publishing. Registration can either be done individually, or as a group as a metric set. The intention is for all metrics in a set to be updated in one go, although it is also possible for metrics within a set to be updated individually. It is up to the producers to update metrics as required. Bit-rate statistics library --------------------------- The bit-rate library calculates the mean, the exponentially-weighted moving average, and peak bit-rates for each active port (i.e. network device). These statistics are then reported via the metrics library using the following names: mean_bits_in, mean_bits_out, ewma_bits_in, ewma_bits_out, peak_bits_in, and peak_bits_out. The sampling window used for calculation is decided by the application requiring the statistics. Latency statistics library -------------------------- The latency statistics library calculates the port-to-port latency of packet processing by a DPDK application, reporting the minimum, average, and maximum nano-seconds that packet processing takes, as well as the jitter in processing delay. These statistics are then reported via the metrics library using the following names: min_latency_ns, avg_latency_ns, mac_latency_ns, and jitter_ns. For more details on the metrics library and the Bit-rate and Latency components see the Programmer's Guide updates in the patchset. -- v11 changes: * Rebased * .map references to 17.02 changed to 17.05 * Release ntoes moved to release_17_05.rst * Bit-rate library now also gives unfiltered average v10 changes: * Rebased * Relocated some config-related directives. * Removed incorrect capitalisations in API docs. * Formatting & detail corrections in release notes. * Moved around struct member descriptions. * Rewritten rte_metrics.h file description. * Rewritten description of RTE_METRICS_GLOBAL. * Used 'producers' and 'consumers' as terms. * Removed markup (bold text) in Doxygen tags. * Added programming guide section. v9 changes: * Updated .map files to reflect function changes in v8 * Fixed rte_malloc() of zero bytes in proc_info when no metrics exist * Fixed rte_metrics_init not being called explicitly in testpmd v8 changes: * Release notes correction * Updated copyright years * rte_metric_init() takes socket id & must be explicitly called * rte_metrics_reg_metric renamed to rte_metrics_reg_name() * rte_metrics_update_metric() renamed to rte_metrics_update_value() * Doxygen updates * Changed malloc()/free() to rte_malloc()/rte_free() * Removed redundant memset() * rte_stats_bitrates_s renamed to rte_stats_bitrates_s * Split mbuf change to own patch for visibility * CYCLES_PER_NS now a static inline function * latency: "hidden" pthread creation now has polling API instead. * Struct declarations and variable definitions cleaned up * Double initialization of the latency library now returns -EEXIST * MAINTAINERS entry for layenctstats in correct section v7 changes: * RTE_METRICS_NONPORT renamed to RTE_METRICS_GLOBAL * Multiple changes to rte_metrics.h doxygen documentation * Split apart latency patch into lib, test-pmd, & proc_info parts * Reordered patches by functionality * Insufficent capacity return value changed from -ERANGE to actual size * Cache alignment in bitrate library * Tightened up const usage to avoid STATIC_CONST_CHAR_ARRAY warning * Reshma reinstated as author for (now split) latency patch * Rebase to master v6 changes: * Metrics display now has "Non port specific" rather than "port -1" * Fixed sign issue in EWMA delta calculation * Rebased to master v5 changes: * Updated Shared Library Versions in release notes * Merged in Reshma's latencystats library v4 changes: * References to 16.11 changed to 17.02 * Fetching of non-port values was broken * Added sanity checks to value fetching * rte_stat_value renamed to rte_metric_value * Corrected doxygen descriptions * Added MAINTAINERS entries * Added #ifdef directives to bitrate code in test-pmd v3 changes: * Marked rte_stats_bitrate_s as internal * Minor integer roundoff correction * Coding style corrections * Removed spurious object allocation * Changes to rte_metrics.[ch] moved from Patch 2/3 to 1/3. * Reintroduced non-port values (RTE_METRICS_NONPORT) * Added spinlocks to metric library * Removed spurious test registration/update * Added release notes entries v2 changes: * Uses a new metrics library rather than being part of ethdev Harry van Haaren (3): mbuf: add a timestamp to the mbuf for latencystats lib: added new library for latency stats app/test-pmd: add latency statistics calculation Remy Horton (3): lib: add information metrics library lib: add bitrate statistics library app/test-pmd: add bitrate statistics calculation Reshma Pattan (1): app/proc_info: add metrics displaying MAINTAINERS | 12 + app/proc_info/main.c | 79 ++++- app/test-pmd/parameters.c | 20 +- app/test-pmd/testpmd.c | 78 ++++- app/test-pmd/testpmd.h | 6 +- config/common_base | 15 + doc/api/doxy-api-index.md | 3 + doc/api/doxy-api.conf | 3 + doc/guides/prog_guide/index.rst | 1 + doc/guides/prog_guide/metrics_lib.rst | 299 +++++++++++++++++ doc/guides/rel_notes/release_17_02.rst | 3 + doc/guides/rel_notes/release_17_05.rst | 18 + lib/Makefile | 3 + lib/librte_bitratestats/Makefile | 53 +++ lib/librte_bitratestats/rte_bitrate.c | 141 ++++++++ lib/librte_bitratestats/rte_bitrate.h | 80 +++++ .../rte_bitratestats_version.map | 9 + lib/librte_latencystats/Makefile | 56 ++++ lib/librte_latencystats/rte_latencystats.c | 366 +++++++++++++++++++++ lib/librte_latencystats/rte_latencystats.h | 154 +++++++++ .../rte_latencystats_version.map | 11 + lib/librte_mbuf/rte_mbuf.h | 3 + lib/librte_metrics/Makefile | 51 +++ lib/librte_metrics/rte_metrics.c | 299 +++++++++++++++++ lib/librte_metrics/rte_metrics.h | 240 ++++++++++++++ lib/librte_metrics/rte_metrics_version.map | 13 + mk/rte.app.mk | 3 + 27 files changed, 2015 insertions(+), 4 deletions(-) create mode 100644 doc/guides/prog_guide/metrics_lib.rst create mode 100644 lib/librte_bitratestats/Makefile create mode 100644 lib/librte_bitratestats/rte_bitrate.c create mode 100644 lib/librte_bitratestats/rte_bitrate.h create mode 100644 lib/librte_bitratestats/rte_bitratestats_version.map create mode 100644 lib/librte_latencystats/Makefile create mode 100644 lib/librte_latencystats/rte_latencystats.c create mode 100644 lib/librte_latencystats/rte_latencystats.h create mode 100644 lib/librte_latencystats/rte_latencystats_version.map create mode 100644 lib/librte_metrics/Makefile create mode 100644 lib/librte_metrics/rte_metrics.c create mode 100644 lib/librte_metrics/rte_metrics.h create mode 100644 lib/librte_metrics/rte_metrics_version.map -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v11 1/7] lib: add information metrics library 2017-03-09 16:25 ` [dpdk-dev] [PATCH v11 " Remy Horton @ 2017-03-09 16:25 ` Remy Horton 2017-03-09 16:25 ` [dpdk-dev] [PATCH v11 2/7] app/proc_info: add metrics displaying Remy Horton ` (5 subsequent siblings) 6 siblings, 0 replies; 115+ messages in thread From: Remy Horton @ 2017-03-09 16:25 UTC (permalink / raw) To: dev; +Cc: Thomas Monjalon This patch adds a new information metrics library. This Metrics library implements a mechanism by which producers can publish numeric information for later querying by consumers. Metrics themselves are statistics that are not generated by PMDs, and hence are not reported via ethdev extended statistics. Metric information is populated using a push model, where producers update the values contained within the metric library by calling an update function on the relevant metrics. Consumers receive metric information by querying the central metric data, which is held in shared memory. Signed-off-by: Remy Horton <remy.horton@intel.com> --- MAINTAINERS | 4 + config/common_base | 5 + doc/api/doxy-api-index.md | 1 + doc/api/doxy-api.conf | 1 + doc/guides/prog_guide/index.rst | 1 + doc/guides/prog_guide/metrics_lib.rst | 180 +++++++++++++++++ doc/guides/rel_notes/release_17_02.rst | 1 + doc/guides/rel_notes/release_17_05.rst | 8 + lib/Makefile | 1 + lib/librte_metrics/Makefile | 51 +++++ lib/librte_metrics/rte_metrics.c | 299 +++++++++++++++++++++++++++++ lib/librte_metrics/rte_metrics.h | 240 +++++++++++++++++++++++ lib/librte_metrics/rte_metrics_version.map | 13 ++ mk/rte.app.mk | 2 + 14 files changed, 807 insertions(+) create mode 100644 doc/guides/prog_guide/metrics_lib.rst create mode 100644 lib/librte_metrics/Makefile create mode 100644 lib/librte_metrics/rte_metrics.c create mode 100644 lib/librte_metrics/rte_metrics.h create mode 100644 lib/librte_metrics/rte_metrics_version.map diff --git a/MAINTAINERS b/MAINTAINERS index 5030c1c..66478f3 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -635,6 +635,10 @@ F: lib/librte_jobstats/ F: examples/l2fwd-jobstats/ F: doc/guides/sample_app_ug/l2_forward_job_stats.rst +Metrics +M: Remy Horton <remy.horton@intel.com> +F: lib/librte_metrics/ + Test Applications ----------------- diff --git a/config/common_base b/config/common_base index aeee13e..cea055f 100644 --- a/config/common_base +++ b/config/common_base @@ -501,6 +501,11 @@ CONFIG_RTE_LIBRTE_EFD=y CONFIG_RTE_LIBRTE_JOBSTATS=y # +# Compile the device metrics library +# +CONFIG_RTE_LIBRTE_METRICS=y + +# # Compile librte_lpm # CONFIG_RTE_LIBRTE_LPM=y diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md index eb39f69..26a26b7 100644 --- a/doc/api/doxy-api-index.md +++ b/doc/api/doxy-api-index.md @@ -156,4 +156,5 @@ There are many libraries, so their headers may be grouped by topics: [common] (@ref rte_common.h), [ABI compat] (@ref rte_compat.h), [keepalive] (@ref rte_keepalive.h), + [device metrics] (@ref rte_metrics.h), [version] (@ref rte_version.h) diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf index fdcf13c..fbbcf8e 100644 --- a/doc/api/doxy-api.conf +++ b/doc/api/doxy-api.conf @@ -52,6 +52,7 @@ INPUT = doc/api/doxy-api-index.md \ lib/librte_mbuf \ lib/librte_mempool \ lib/librte_meter \ + lib/librte_metrics \ lib/librte_net \ lib/librte_pdump \ lib/librte_pipeline \ diff --git a/doc/guides/prog_guide/index.rst b/doc/guides/prog_guide/index.rst index 77f427e..2a69844 100644 --- a/doc/guides/prog_guide/index.rst +++ b/doc/guides/prog_guide/index.rst @@ -62,6 +62,7 @@ Programmer's Guide packet_classif_access_ctrl packet_framework vhost_lib + metrics_lib port_hotplug_framework source_org dev_kit_build_system diff --git a/doc/guides/prog_guide/metrics_lib.rst b/doc/guides/prog_guide/metrics_lib.rst new file mode 100644 index 0000000..87f806d --- /dev/null +++ b/doc/guides/prog_guide/metrics_lib.rst @@ -0,0 +1,180 @@ +.. BSD LICENSE + Copyright(c) 2017 Intel Corporation. All rights reserved. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + * Neither the name of Intel Corporation nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +.. _Metrics_Library: + +Metrics Library +=============== + +The Metrics library implements a mechanism by which *producers* can +publish numeric information for later querying by *consumers*. In +practice producers will typically be other libraries or primary +processes, whereas consumers will typically be applications. + +Metrics themselves are statistics that are not generated by PMDs. Metric +information is populated using a push model, where producers update the +values contained within the metric library by calling an update function +on the relevant metrics. Consumers receive metric information by querying +the central metric data, which is held in shared memory. + +For each metric, a separate value is maintained for each port id, and +when publishing metric values the producers need to specify which port is +being updated. In addition there is a special id ``RTE_METRICS_GLOBAL`` +that is intended for global statistics that are not associated with any +individual device. Since the metrics library is self-contained, the only +restriction on port numbers is that they are less than ``RTE_MAX_ETHPORTS`` +- there is no requirement for the ports to actually exist. + +Initialising the library +------------------------ + +Before the library can be used, it has to be initialized by calling +``rte_metrics_init()`` which sets up the metric store in shared memory. +This is where producers will publish metric information to, and where +consumers will query it from. + +.. code-block:: c + + rte_metrics_init(rte_socket_id()); + +This function **must** be called from a primary process, but otherwise +producers and consumers can be in either primary or secondary processes. + +Registering metrics +------------------- + +Metrics must first be *registered*, which is the way producers declare +the names of the metrics they will be publishing. Registration can either +be done individually, or a set of metrics can be registered as a group. +Individual registration is done using ``rte_metrics_reg_name()``: + +.. code-block:: c + + id_1 = rte_metrics_reg_name("mean_bits_in"); + id_2 = rte_metrics_reg_name("mean_bits_out"); + id_3 = rte_metrics_reg_name("peak_bits_in"); + id_4 = rte_metrics_reg_name("peak_bits_out"); + +or alternatively, a set of metrics can be registered together using +``rte_metrics_reg_names()``: + +.. code-block:: c + + const char * const names[] = { + "mean_bits_in", "mean_bits_out", + "peak_bits_in", "peak_bits_out", + }; + id_set = rte_metrics_reg_names(&names[0], 4); + +If the return value is negative, it means registration failed. Otherwise +the return value is the *key* for the metric, which is used when updating +values. A table mapping together these key values and the metrics' names +can be obtained using ``rte_metrics_get_names()``. + +Updating metric values +---------------------- + +Once registered, producers can update the metric for a given port using +the ``rte_metrics_update_value()`` function. This uses the metric key +that is returned when registering the metric, and can also be looked up +using ``rte_metrics_get_names()``. + +.. code-block:: c + + rte_metrics_update_value(port_id, id_1, values[0]); + rte_metrics_update_value(port_id, id_2, values[1]); + rte_metrics_update_value(port_id, id_3, values[2]); + rte_metrics_update_value(port_id, id_4, values[3]); + +if metrics were registered as a single set, they can either be updated +individually using ``rte_metrics_update_value()``, or updated together +using the ``rte_metrics_update_values()`` function: + +.. code-block:: c + + rte_metrics_update_value(port_id, id_set, values[0]); + rte_metrics_update_value(port_id, id_set + 1, values[1]); + rte_metrics_update_value(port_id, id_set + 2, values[2]); + rte_metrics_update_value(port_id, id_set + 3, values[3]); + + rte_metrics_update_values(port_id, id_set, values, 4); + +Note that ``rte_metrics_update_values()`` cannot be used to update +metric values from *multiple* *sets*, as there is no guarantee two +sets registered one after the other have contiguous id values. + +Querying metrics +---------------- + +Consumers can obtain metric values by querying the metrics library using +the ``rte_metrics_get_values()`` function that return an array of +``struct rte_metric_value``. Each entry within this array contains a metric +value and its associated key. A key-name mapping can be obtained using the +``rte_metrics_get_names()`` function that returns an array of +``struct rte_metric_name`` that is indexed by the key. The following will +print out all metrics for a given port: + +.. code-block:: c + + void print_metrics() { + struct rte_metric_name *names; + int len; + + len = rte_metrics_get_names(NULL, 0); + if (len < 0) { + printf("Cannot get metrics count\n"); + return; + } + if (len == 0) { + printf("No metrics to display (none have been registered)\n"); + return; + } + metrics = malloc(sizeof(struct rte_metric_value) * len); + names = malloc(sizeof(struct rte_metric_name) * len); + if (metrics == NULL || names == NULL) { + printf("Cannot allocate memory\n"); + free(metrics); + free(names); + return; + } + ret = rte_metrics_get_values(port_id, metrics, len); + if (ret < 0 || ret > len) { + printf("Cannot get metrics values\n"); + free(metrics); + free(names); + return; + } + printf("Metrics for port %i:\n", port_id); + for (i = 0; i < len; i++) + printf(" %s: %"PRIu64"\n", + names[metrics[i].key].name, metrics[i].value); + free(metrics); + free(names); + } diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst index 357965a..8bd706f 100644 --- a/doc/guides/rel_notes/release_17_02.rst +++ b/doc/guides/rel_notes/release_17_02.rst @@ -368,6 +368,7 @@ The libraries prepended with a plus sign were incremented in this version. librte_mbuf.so.2 librte_mempool.so.2 librte_meter.so.1 + + librte_metrics.so.1 librte_net.so.1 librte_pdump.so.1 librte_pipeline.so.3 diff --git a/doc/guides/rel_notes/release_17_05.rst b/doc/guides/rel_notes/release_17_05.rst index e25ea9f..3ed809e 100644 --- a/doc/guides/rel_notes/release_17_05.rst +++ b/doc/guides/rel_notes/release_17_05.rst @@ -61,6 +61,14 @@ Resolved Issues Also, make sure to start the actual text at the margin. ========================================================= +* **Added information metric library.** + + A library that allows information metrics to be added and updated + by producers, typically other libraries, for later retrieval by + consumers such as applications. It is intended to provide a + reporting mechanism that is independent of other libraries such + as ethdev. + EAL ~~~ diff --git a/lib/Makefile b/lib/Makefile index 4178325..29f6a81 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -49,6 +49,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_ACL) += librte_acl DIRS-$(CONFIG_RTE_LIBRTE_NET) += librte_net DIRS-$(CONFIG_RTE_LIBRTE_IP_FRAG) += librte_ip_frag DIRS-$(CONFIG_RTE_LIBRTE_JOBSTATS) += librte_jobstats +DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics DIRS-$(CONFIG_RTE_LIBRTE_POWER) += librte_power DIRS-$(CONFIG_RTE_LIBRTE_METER) += librte_meter DIRS-$(CONFIG_RTE_LIBRTE_SCHED) += librte_sched diff --git a/lib/librte_metrics/Makefile b/lib/librte_metrics/Makefile new file mode 100644 index 0000000..8d6e23a --- /dev/null +++ b/lib/librte_metrics/Makefile @@ -0,0 +1,51 @@ +# BSD LICENSE +# +# Copyright(c) 2016 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +include $(RTE_SDK)/mk/rte.vars.mk + +# library name +LIB = librte_metrics.a + +CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) + +EXPORT_MAP := rte_metrics_version.map + +LIBABIVER := 1 + +# all source are stored in SRCS-y +SRCS-$(CONFIG_RTE_LIBRTE_METRICS) := rte_metrics.c + +# Install header file +SYMLINK-$(CONFIG_RTE_LIBRTE_METRICS)-include += rte_metrics.h + +DEPDIRS-$(CONFIG_RTE_LIBRTE_METRICS) += lib/librte_eal + +include $(RTE_SDK)/mk/rte.lib.mk diff --git a/lib/librte_metrics/rte_metrics.c b/lib/librte_metrics/rte_metrics.c new file mode 100644 index 0000000..aa9ec50 --- /dev/null +++ b/lib/librte_metrics/rte_metrics.c @@ -0,0 +1,299 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016-2017 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <string.h> +#include <sys/queue.h> + +#include <rte_common.h> +#include <rte_malloc.h> +#include <rte_metrics.h> +#include <rte_lcore.h> +#include <rte_memzone.h> +#include <rte_spinlock.h> + +#define RTE_METRICS_MAX_METRICS 256 +#define RTE_METRICS_MEMZONE_NAME "RTE_METRICS" + +/** + * Internal stats metadata and value entry. + * + * @internal + */ +struct rte_metrics_meta_s { + /** Name of metric */ + char name[RTE_METRICS_MAX_NAME_LEN]; + /** Current value for metric */ + uint64_t value[RTE_MAX_ETHPORTS]; + /** Used for global metrics */ + uint64_t global_value; + /** Index of next root element (zero for none) */ + uint16_t idx_next_set; + /** Index of next metric in set (zero for none) */ + uint16_t idx_next_stat; +}; + +/** + * Internal stats info structure. + * + * @internal + * Offsets into metadata are used instead of pointers because ASLR + * means that having the same physical addresses in different + * processes is not guaranteed. + */ +struct rte_metrics_data_s { + /** Index of last metadata entry with valid data. + * This value is not valid if cnt_stats is zero. + */ + uint16_t idx_last_set; + /** Number of metrics. */ + uint16_t cnt_stats; + /** Metric data memory block. */ + struct rte_metrics_meta_s metadata[RTE_METRICS_MAX_METRICS]; + /** Metric data access lock */ + rte_spinlock_t lock; +}; + +void +rte_metrics_init(int socket_id) +{ + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + + if (rte_eal_process_type() != RTE_PROC_PRIMARY) + return; + + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); + if (memzone != NULL) + return; + memzone = rte_memzone_reserve(RTE_METRICS_MEMZONE_NAME, + sizeof(struct rte_metrics_data_s), socket_id, 0); + if (memzone == NULL) + rte_exit(EXIT_FAILURE, "Unable to allocate stats memzone\n"); + stats = memzone->addr; + memset(stats, 0, sizeof(struct rte_metrics_data_s)); + rte_spinlock_init(&stats->lock); +} + +int +rte_metrics_reg_name(const char *name) +{ + const char * const list_names[] = {name}; + + return rte_metrics_reg_names(list_names, 1); +} + +int +rte_metrics_reg_names(const char * const *names, uint16_t cnt_names) +{ + struct rte_metrics_meta_s *entry; + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + uint16_t idx_name; + uint16_t idx_base; + + /* Some sanity checks */ + if (cnt_names < 1 || names == NULL) + return -EINVAL; + + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); + if (memzone == NULL) + return -EIO; + stats = memzone->addr; + + if (stats->cnt_stats + cnt_names >= RTE_METRICS_MAX_METRICS) + return -ENOMEM; + + rte_spinlock_lock(&stats->lock); + + /* Overwritten later if this is actually first set.. */ + stats->metadata[stats->idx_last_set].idx_next_set = stats->cnt_stats; + + stats->idx_last_set = idx_base = stats->cnt_stats; + + for (idx_name = 0; idx_name < cnt_names; idx_name++) { + entry = &stats->metadata[idx_name + stats->cnt_stats]; + strncpy(entry->name, names[idx_name], + RTE_METRICS_MAX_NAME_LEN); + memset(entry->value, 0, sizeof(entry->value)); + entry->idx_next_stat = idx_name + stats->cnt_stats + 1; + } + entry->idx_next_stat = 0; + entry->idx_next_set = 0; + stats->cnt_stats += cnt_names; + + rte_spinlock_unlock(&stats->lock); + + return idx_base; +} + +int +rte_metrics_update_value(int port_id, uint16_t key, const uint64_t value) +{ + return rte_metrics_update_values(port_id, key, &value, 1); +} + +int +rte_metrics_update_values(int port_id, + uint16_t key, + const uint64_t *values, + uint32_t count) +{ + struct rte_metrics_meta_s *entry; + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + uint16_t idx_metric; + uint16_t idx_value; + uint16_t cnt_setsize; + + if (port_id != RTE_METRICS_GLOBAL && + (port_id < 0 || port_id > RTE_MAX_ETHPORTS)) + return -EINVAL; + + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); + if (memzone == NULL) + return -EIO; + stats = memzone->addr; + + rte_spinlock_lock(&stats->lock); + idx_metric = key; + cnt_setsize = 1; + while (idx_metric < stats->cnt_stats) { + entry = &stats->metadata[idx_metric]; + if (entry->idx_next_stat == 0) + break; + cnt_setsize++; + idx_metric++; + } + /* Check update does not cross set border */ + if (count > cnt_setsize) { + rte_spinlock_unlock(&stats->lock); + return -ERANGE; + } + + if (port_id == RTE_METRICS_GLOBAL) + for (idx_value = 0; idx_value < count; idx_value++) { + idx_metric = key + idx_value; + stats->metadata[idx_metric].global_value = + values[idx_value]; + } + else + for (idx_value = 0; idx_value < count; idx_value++) { + idx_metric = key + idx_value; + stats->metadata[idx_metric].value[port_id] = + values[idx_value]; + } + rte_spinlock_unlock(&stats->lock); + return 0; +} + +int +rte_metrics_get_names(struct rte_metric_name *names, + uint16_t capacity) +{ + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + uint16_t idx_name; + int return_value; + + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); + /* If not allocated, fail silently */ + if (memzone == NULL) + return 0; + + stats = memzone->addr; + rte_spinlock_lock(&stats->lock); + if (names != NULL) { + if (capacity < stats->cnt_stats) { + return_value = stats->cnt_stats; + rte_spinlock_unlock(&stats->lock); + return return_value; + } + for (idx_name = 0; idx_name < stats->cnt_stats; idx_name++) + strncpy(names[idx_name].name, + stats->metadata[idx_name].name, + RTE_METRICS_MAX_NAME_LEN); + } + return_value = stats->cnt_stats; + rte_spinlock_unlock(&stats->lock); + return return_value; +} + +int +rte_metrics_get_values(int port_id, + struct rte_metric_value *values, + uint16_t capacity) +{ + struct rte_metrics_meta_s *entry; + struct rte_metrics_data_s *stats; + const struct rte_memzone *memzone; + uint16_t idx_name; + int return_value; + + if (port_id != RTE_METRICS_GLOBAL && + (port_id < 0 || port_id > RTE_MAX_ETHPORTS)) + return -EINVAL; + + memzone = rte_memzone_lookup(RTE_METRICS_MEMZONE_NAME); + /* If not allocated, fail silently */ + if (memzone == NULL) + return 0; + stats = memzone->addr; + rte_spinlock_lock(&stats->lock); + + if (values != NULL) { + if (capacity < stats->cnt_stats) { + return_value = stats->cnt_stats; + rte_spinlock_unlock(&stats->lock); + return return_value; + } + if (port_id == RTE_METRICS_GLOBAL) + for (idx_name = 0; + idx_name < stats->cnt_stats; + idx_name++) { + entry = &stats->metadata[idx_name]; + values[idx_name].key = idx_name; + values[idx_name].value = entry->global_value; + } + else + for (idx_name = 0; + idx_name < stats->cnt_stats; + idx_name++) { + entry = &stats->metadata[idx_name]; + values[idx_name].key = idx_name; + values[idx_name].value = entry->value[port_id]; + } + } + return_value = stats->cnt_stats; + rte_spinlock_unlock(&stats->lock); + return return_value; +} diff --git a/lib/librte_metrics/rte_metrics.h b/lib/librte_metrics/rte_metrics.h new file mode 100644 index 0000000..7458328 --- /dev/null +++ b/lib/librte_metrics/rte_metrics.h @@ -0,0 +1,240 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016-2017 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * @file + * + * DPDK Metrics module + * + * Metrics are statistics that are not generated by PMDs, and hence + * are better reported through a mechanism that is independent from + * the ethdev-based extended statistics. Providers will typically + * be other libraries and consumers will typically be applications. + * + * Metric information is populated using a push model, where producers + * update the values contained within the metric library by calling + * an update function on the relevant metrics. Consumers receive + * metric information by querying the central metric data, which is + * held in shared memory. Currently only bulk querying of metrics + * by consumers is supported. + */ + +#ifndef _RTE_METRICS_H_ +#define _RTE_METRICS_H_ + +/** Maximum length of metric name (including null-terminator) */ +#define RTE_METRICS_MAX_NAME_LEN 64 + +/** + * Global metric special id. + * + * When used for the port_id parameter when calling + * rte_metrics_update_metric() or rte_metrics_update_metric(), + * the global metric, which are not associated with any specific + * port (i.e. device), are updated. + */ +#define RTE_METRICS_GLOBAL -1 + + +/** + * A name-key lookup for metrics. + * + * An array of this structure is returned by rte_metrics_get_names(). + * The struct rte_metric_value references these names via their array index. + */ +struct rte_metric_name { + /** String describing metric */ + char name[RTE_METRICS_MAX_NAME_LEN]; +}; + + +/** + * Metric value structure. + * + * This structure is used by rte_metrics_get_values() to return metrics, + * which are statistics that are not generated by PMDs. It maps a name key, + * which corresponds to an index in the array returned by + * rte_metrics_get_names(). + */ +struct rte_metric_value { + /** Numeric identifier of metric. */ + uint16_t key; + /** Value for metric */ + uint64_t value; +}; + + +/** + * Initializes metric module. This function must be called from + * a primary process before metrics are used. + * + * @param socket_id + * Socket to use for shared memory allocation. + */ +void rte_metrics_init(int socket_id); + +/** + * Register a metric, making it available as a reporting parameter. + * + * Registering a metric is the way producers declare a parameter + * that they wish to be reported. Once registered, the associated + * numeric key can be obtained via rte_metrics_get_names(), which + * is required for updating said metric's value. + * + * @param name + * Metric name + * + * @return + * - Zero or positive: Success (index key of new metric) + * - -EIO: Error, unable to access metrics shared memory + * (rte_metrics_init() not called) + * - -EINVAL: Error, invalid parameters + * - -ENOMEM: Error, maximum metrics reached + */ +int rte_metrics_reg_name(const char *name); + +/** + * Register a set of metrics. + * + * This is a bulk version of rte_metrics_reg_metrics() and aside from + * handling multiple keys at once is functionally identical. + * + * @param names + * List of metric names + * + * @param cnt_names + * Number of metrics in set + * + * @return + * - Zero or positive: Success (index key of start of set) + * - -EIO: Error, unable to access metrics shared memory + * (rte_metrics_init() not called) + * - -EINVAL: Error, invalid parameters + * - -ENOMEM: Error, maximum metrics reached + */ +int rte_metrics_reg_names(const char * const *names, uint16_t cnt_names); + +/** + * Get metric name-key lookup table. + * + * @param names + * A struct rte_metric_name array of at least *capacity* in size to + * receive key names. If this is NULL, function returns the required + * number of elements for this array. + * + * @param capacity + * Size (number of elements) of struct rte_metric_name array. + * Disregarded if names is NULL. + * + * @return + * - Positive value above capacity: error, *names* is too small. + * Return value is required size. + * - Positive value equal or less than capacity: Success. Return + * value is number of elements filled in. + * - Negative value: error. + */ +int rte_metrics_get_names( + struct rte_metric_name *names, + uint16_t capacity); + +/** + * Get metric value table. + * + * @param port_id + * Port id to query + * + * @param values + * A struct rte_metric_value array of at least *capacity* in size to + * receive metric ids and values. If this is NULL, function returns + * the required number of elements for this array. + * + * @param capacity + * Size (number of elements) of struct rte_metric_value array. + * Disregarded if names is NULL. + * + * @return + * - Positive value above capacity: error, *values* is too small. + * Return value is required size. + * - Positive value equal or less than capacity: Success. Return + * value is number of elements filled in. + * - Negative value: error. + */ +int rte_metrics_get_values( + int port_id, + struct rte_metric_value *values, + uint16_t capacity); + +/** + * Updates a metric + * + * @param port_id + * Port to update metrics for + * @param key + * Id of metric to update + * @param value + * New value + * + * @return + * - -EIO if unable to access shared metrics memory + * - Zero on success + */ +int rte_metrics_update_value( + int port_id, + uint16_t key, + const uint64_t value); + +/** + * Updates a metric set. Note that it is an error to try to + * update across a set boundary. + * + * @param port_id + * Port to update metrics for + * @param key + * Base id of metrics set to update + * @param values + * Set of new values + * @param count + * Number of new values + * + * @return + * - -ERANGE if count exceeds metric set size + * - -EIO if upable to access shared metrics memory + * - Zero on success + */ +int rte_metrics_update_values( + int port_id, + uint16_t key, + const uint64_t *values, + uint32_t count); + +#endif diff --git a/lib/librte_metrics/rte_metrics_version.map b/lib/librte_metrics/rte_metrics_version.map new file mode 100644 index 0000000..4c5234c --- /dev/null +++ b/lib/librte_metrics/rte_metrics_version.map @@ -0,0 +1,13 @@ +DPDK_17.05 { + global: + + rte_metrics_get_names; + rte_metrics_get_values; + rte_metrics_init; + rte_metrics_reg_name; + rte_metrics_reg_names; + rte_metrics_update_value; + rte_metrics_update_values; + + local: *; +}; diff --git a/mk/rte.app.mk b/mk/rte.app.mk index d46a33e..98eb052 100644 --- a/mk/rte.app.mk +++ b/mk/rte.app.mk @@ -99,6 +99,8 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_RING) += -lrte_ring _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL) += -lrte_eal _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE) += -lrte_cmdline _LDLIBS-$(CONFIG_RTE_LIBRTE_REORDER) += -lrte_reorder +_LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS) += -lrte_metrics + ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),n) # plugins (link only if static libraries) -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v11 2/7] app/proc_info: add metrics displaying 2017-03-09 16:25 ` [dpdk-dev] [PATCH v11 " Remy Horton 2017-03-09 16:25 ` [dpdk-dev] [PATCH v11 1/7] lib: add information metrics library Remy Horton @ 2017-03-09 16:25 ` Remy Horton 2017-03-09 16:25 ` [dpdk-dev] [PATCH v11 3/7] lib: add bitrate statistics library Remy Horton ` (4 subsequent siblings) 6 siblings, 0 replies; 115+ messages in thread From: Remy Horton @ 2017-03-09 16:25 UTC (permalink / raw) To: dev; +Cc: Reshma Pattan, Thomas Monjalon From: Reshma Pattan <reshma.pattan@intel.com> Modify the dpdk-procinfo process to display the newly added metrics. Added new command line option "--metrics" to display metrics. Signed-off-by: Reshma Pattan <reshma.pattan@intel.com> Signed-off-by: Remy Horton <remy.horton@intel.com> --- app/proc_info/main.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 78 insertions(+), 1 deletion(-) diff --git a/app/proc_info/main.c b/app/proc_info/main.c index 2c56d10..f513669 100644 --- a/app/proc_info/main.c +++ b/app/proc_info/main.c @@ -1,7 +1,7 @@ /* * BSD LICENSE * - * Copyright(c) 2010-2016 Intel Corporation. All rights reserved. + * Copyright(c) 2010-2017 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -57,6 +57,7 @@ #include <rte_atomic.h> #include <rte_branch_prediction.h> #include <rte_string_fns.h> +#include <rte_metrics.h> /* Maximum long option length for option parsing. */ #define MAX_LONG_OPT_SZ 64 @@ -68,6 +69,8 @@ static uint32_t enabled_port_mask; static uint32_t enable_stats; /**< Enable xstats. */ static uint32_t enable_xstats; +/**< Enable metrics. */ +static uint32_t enable_metrics; /**< Enable stats reset. */ static uint32_t reset_stats; /**< Enable xstats reset. */ @@ -85,6 +88,8 @@ proc_info_usage(const char *prgname) " --stats: to display port statistics, enabled by default\n" " --xstats: to display extended port statistics, disabled by " "default\n" + " --metrics: to display derived metrics of the ports, disabled by " + "default\n" " --stats-reset: to reset port statistics\n" " --xstats-reset: to reset port extended statistics\n", prgname); @@ -127,6 +132,7 @@ proc_info_parse_args(int argc, char **argv) {"stats", 0, NULL, 0}, {"stats-reset", 0, NULL, 0}, {"xstats", 0, NULL, 0}, + {"metrics", 0, NULL, 0}, {"xstats-reset", 0, NULL, 0}, {NULL, 0, 0, 0} }; @@ -159,6 +165,10 @@ proc_info_parse_args(int argc, char **argv) else if (!strncmp(long_option[option_index].name, "xstats", MAX_LONG_OPT_SZ)) enable_xstats = 1; + else if (!strncmp(long_option[option_index].name, + "metrics", + MAX_LONG_OPT_SZ)) + enable_metrics = 1; /* Reset stats */ if (!strncmp(long_option[option_index].name, "stats-reset", MAX_LONG_OPT_SZ)) @@ -301,6 +311,67 @@ nic_xstats_clear(uint8_t port_id) printf("\n NIC extended statistics for port %d cleared\n", port_id); } +static void +metrics_display(int port_id) +{ + struct rte_metric_value *metrics; + struct rte_metric_name *names; + int len, ret; + static const char *nic_stats_border = "########################"; + + len = rte_metrics_get_names(NULL, 0); + if (len < 0) { + printf("Cannot get metrics count\n"); + return; + } + if (len == 0) { + printf("No metrics to display (none have been registered)\n"); + return; + } + + metrics = rte_malloc("proc_info_metrics", + sizeof(struct rte_metric_value) * len, 0); + if (metrics == NULL) { + printf("Cannot allocate memory for metrics\n"); + return; + } + + names = rte_malloc(NULL, sizeof(struct rte_metric_name) * len, 0); + if (names == NULL) { + printf("Cannot allocate memory for metrcis names\n"); + rte_free(metrics); + return; + } + + if (len != rte_metrics_get_names(names, len)) { + printf("Cannot get metrics names\n"); + rte_free(metrics); + rte_free(names); + return; + } + + if (port_id == RTE_METRICS_GLOBAL) + printf("###### Non port specific metrics #########\n"); + else + printf("###### metrics for port %-2d #########\n", port_id); + printf("%s############################\n", nic_stats_border); + ret = rte_metrics_get_values(port_id, metrics, len); + if (ret < 0 || ret > len) { + printf("Cannot get metrics values\n"); + rte_free(metrics); + rte_free(names); + return; + } + + int i; + for (i = 0; i < len; i++) + printf("%s: %"PRIu64"\n", names[i].name, metrics[i].value); + + printf("%s############################\n", nic_stats_border); + rte_free(metrics); + rte_free(names); +} + int main(int argc, char **argv) { @@ -360,8 +431,14 @@ main(int argc, char **argv) nic_stats_clear(i); else if (reset_xstats) nic_xstats_clear(i); + else if (enable_metrics) + metrics_display(i); } } + /* print port independent stats */ + if (enable_metrics) + metrics_display(RTE_METRICS_GLOBAL); + return 0; } -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v11 3/7] lib: add bitrate statistics library 2017-03-09 16:25 ` [dpdk-dev] [PATCH v11 " Remy Horton 2017-03-09 16:25 ` [dpdk-dev] [PATCH v11 1/7] lib: add information metrics library Remy Horton 2017-03-09 16:25 ` [dpdk-dev] [PATCH v11 2/7] app/proc_info: add metrics displaying Remy Horton @ 2017-03-09 16:25 ` Remy Horton 2017-03-09 16:25 ` [dpdk-dev] [PATCH v11 4/7] app/test-pmd: add bitrate statistics calculation Remy Horton ` (3 subsequent siblings) 6 siblings, 0 replies; 115+ messages in thread From: Remy Horton @ 2017-03-09 16:25 UTC (permalink / raw) To: dev; +Cc: Thomas Monjalon This patch adds a library that calculates peak and average data-rate statistics. For ethernet devices. These statistics are reported using the metrics library. Signed-off-by: Remy Horton <remy.horton@intel.com> --- MAINTAINERS | 4 + config/common_base | 5 + doc/api/doxy-api-index.md | 1 + doc/api/doxy-api.conf | 1 + doc/guides/prog_guide/metrics_lib.rst | 65 ++++++++++ doc/guides/rel_notes/release_17_02.rst | 1 + doc/guides/rel_notes/release_17_05.rst | 5 + lib/Makefile | 1 + lib/librte_bitratestats/Makefile | 53 ++++++++ lib/librte_bitratestats/rte_bitrate.c | 141 +++++++++++++++++++++ lib/librte_bitratestats/rte_bitrate.h | 80 ++++++++++++ .../rte_bitratestats_version.map | 9 ++ mk/rte.app.mk | 1 + 13 files changed, 367 insertions(+) create mode 100644 lib/librte_bitratestats/Makefile create mode 100644 lib/librte_bitratestats/rte_bitrate.c create mode 100644 lib/librte_bitratestats/rte_bitrate.h create mode 100644 lib/librte_bitratestats/rte_bitratestats_version.map diff --git a/MAINTAINERS b/MAINTAINERS index 66478f3..8abf4fd 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -639,6 +639,10 @@ Metrics M: Remy Horton <remy.horton@intel.com> F: lib/librte_metrics/ +Bit-rate statistica +M: Remy Horton <remy.horton@intel.com> +F: lib/librte_bitratestats/ + Test Applications ----------------- diff --git a/config/common_base b/config/common_base index cea055f..d700ee0 100644 --- a/config/common_base +++ b/config/common_base @@ -630,3 +630,8 @@ CONFIG_RTE_TEST_PMD_RECORD_BURST_STATS=n # Compile the crypto performance application # CONFIG_RTE_APP_CRYPTO_PERF=y + +# +# Compile the bitrate statistics library +# +CONFIG_RTE_LIBRTE_BITRATE=y diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md index 26a26b7..8492bce 100644 --- a/doc/api/doxy-api-index.md +++ b/doc/api/doxy-api-index.md @@ -157,4 +157,5 @@ There are many libraries, so their headers may be grouped by topics: [ABI compat] (@ref rte_compat.h), [keepalive] (@ref rte_keepalive.h), [device metrics] (@ref rte_metrics.h), + [bitrate statistics] (@ref rte_bitrate.h), [version] (@ref rte_version.h) diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf index fbbcf8e..c4b3b68 100644 --- a/doc/api/doxy-api.conf +++ b/doc/api/doxy-api.conf @@ -36,6 +36,7 @@ INPUT = doc/api/doxy-api-index.md \ lib/librte_eal/common/include \ lib/librte_eal/common/include/generic \ lib/librte_acl \ + lib/librte_bitratestats \ lib/librte_cfgfile \ lib/librte_cmdline \ lib/librte_compat \ diff --git a/doc/guides/prog_guide/metrics_lib.rst b/doc/guides/prog_guide/metrics_lib.rst index 87f806d..1c2a28f 100644 --- a/doc/guides/prog_guide/metrics_lib.rst +++ b/doc/guides/prog_guide/metrics_lib.rst @@ -178,3 +178,68 @@ print out all metrics for a given port: free(metrics); free(names); } + + +Bit-rate statistics library +--------------------------- + +The bit-rate library calculates the exponentially-weighted moving +average and peak bit-rates for each active port (i.e. network device). +These statistics are reported via the metrics library using the +following names: + + - ``mean_bits_in``: Average inbound bit-rate + - ``mean_bits_out``: Average outbound bit-rate + - ``ewma_bits_in``: Average inbound bit-rate (EWMA smoothed) + - ``ewma_bits_out``: Average outbound bit-rate (EWMA smoothed) + - ``peak_bits_in``: Peak inbound bit-rate + - ``peak_bits_out``: Peak outbound bit-rate + +Once initialised and clocked at the appropriate frequency, these +statistics can be obtained by querying the metrics library. + +Initialization +~~~~~~~~~~~~~~ + +Before it is used the bit-rate statistics library has to be initialised +by calling ``rte_stats_bitrate_create()``, which will return a bit-rate +calculation object. Since the bit-rate library uses the metrics library +to report the calculated statistics, the bit-rate library then needs to +register the calculated statistics with the metrics library. This is +done using the helper function ``rte_stats_bitrate_reg()``. + +.. code-block:: c + + struct rte_stats_bitrates *bitrate_data; + + bitrate_data = rte_stats_bitrate_create(); + if (bitrate_data == NULL) + rte_exit(EXIT_FAILURE, "Could not allocate bit-rate data.\n"); + rte_stats_bitrate_reg(bitrate_data); + +Controlling the sampling rate +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Since the library works by periodic sampling but does not use an +internal thread, the application has to periodically call +``rte_stats_bitrate_calc()``. The frequency at which this function +is called should be the intended sampling rate required for the +calculated statistics. For instance if per-second statistics are +desired, this function should be called once a second. + +.. code-block:: c + + tics_datum = rte_rdtsc(); + tics_per_1sec = rte_get_timer_hz(); + + while( 1 ) { + /* ... */ + tics_current = rte_rdtsc(); + if (tics_current - tics_datum >= tics_per_1sec) { + /* Periodic bitrate calculation */ + for (idx_port = 0; idx_port < cnt_ports; idx_port++) + rte_stats_bitrate_calc(bitrate_data, idx_port); + tics_datum = tics_current; + } + /* ... */ + } diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst index 8bd706f..63786df 100644 --- a/doc/guides/rel_notes/release_17_02.rst +++ b/doc/guides/rel_notes/release_17_02.rst @@ -353,6 +353,7 @@ The libraries prepended with a plus sign were incremented in this version. .. code-block:: diff librte_acl.so.2 + + librte_bitratestats.so.1 librte_cfgfile.so.2 librte_cmdline.so.2 librte_cryptodev.so.2 diff --git a/doc/guides/rel_notes/release_17_05.rst b/doc/guides/rel_notes/release_17_05.rst index 3ed809e..83c83b2 100644 --- a/doc/guides/rel_notes/release_17_05.rst +++ b/doc/guides/rel_notes/release_17_05.rst @@ -69,6 +69,11 @@ Resolved Issues reporting mechanism that is independent of other libraries such as ethdev. +* **Added bit-rate calculation library.** + + A library that can be used to calculate device bit-rates. Calculated + bitrates are reported using the metrics library. + EAL ~~~ diff --git a/lib/Makefile b/lib/Makefile index 29f6a81..ecc54c0 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -50,6 +50,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_NET) += librte_net DIRS-$(CONFIG_RTE_LIBRTE_IP_FRAG) += librte_ip_frag DIRS-$(CONFIG_RTE_LIBRTE_JOBSTATS) += librte_jobstats DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics +DIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += librte_bitratestats DIRS-$(CONFIG_RTE_LIBRTE_POWER) += librte_power DIRS-$(CONFIG_RTE_LIBRTE_METER) += librte_meter DIRS-$(CONFIG_RTE_LIBRTE_SCHED) += librte_sched diff --git a/lib/librte_bitratestats/Makefile b/lib/librte_bitratestats/Makefile new file mode 100644 index 0000000..743b62c --- /dev/null +++ b/lib/librte_bitratestats/Makefile @@ -0,0 +1,53 @@ +# BSD LICENSE +# +# Copyright(c) 2016-2017 Intel Corporation. All rights reserved. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +include $(RTE_SDK)/mk/rte.vars.mk + +# library name +LIB = librte_bitratestats.a + +CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) + +EXPORT_MAP := rte_bitratestats_version.map + +LIBABIVER := 1 + +# all source are stored in SRCS-y +SRCS-$(CONFIG_RTE_LIBRTE_BITRATE) := rte_bitrate.c + +# Install header file +SYMLINK-$(CONFIG_RTE_LIBRTE_BITRATE)-include += rte_bitrate.h + +DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_eal +DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_ether +DEPDIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += lib/librte_metrics + +include $(RTE_SDK)/mk/rte.lib.mk diff --git a/lib/librte_bitratestats/rte_bitrate.c b/lib/librte_bitratestats/rte_bitrate.c new file mode 100644 index 0000000..3252598 --- /dev/null +++ b/lib/librte_bitratestats/rte_bitrate.c @@ -0,0 +1,141 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016-2017 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <rte_common.h> +#include <rte_ethdev.h> +#include <rte_malloc.h> +#include <rte_metrics.h> +#include <rte_bitrate.h> + +/* + * Persistent bit-rate data. + * @internal + */ +struct rte_stats_bitrate { + uint64_t last_ibytes; + uint64_t last_obytes; + uint64_t peak_ibits; + uint64_t peak_obits; + uint64_t mean_ibits; + uint64_t mean_obits; + uint64_t ewma_ibits; + uint64_t ewma_obits; +}; + +struct rte_stats_bitrates { + struct rte_stats_bitrate port_stats[RTE_MAX_ETHPORTS]; + uint16_t id_stats_set; +}; + +struct rte_stats_bitrates * +rte_stats_bitrate_create(void) +{ + return rte_zmalloc(NULL, sizeof(struct rte_stats_bitrates), + RTE_CACHE_LINE_SIZE); +} + +int +rte_stats_bitrate_reg(struct rte_stats_bitrates *bitrate_data) +{ + const char * const names[] = { + "ewma_bits_in", "ewma_bits_out", + "mean_bits_in", "mean_bits_out", + "peak_bits_in", "peak_bits_out", + }; + int return_value; + + return_value = rte_metrics_reg_names(&names[0], 6); + if (return_value >= 0) + bitrate_data->id_stats_set = return_value; + return return_value; +} + +int +rte_stats_bitrate_calc(struct rte_stats_bitrates *bitrate_data, + uint8_t port_id) +{ + struct rte_stats_bitrate *port_data; + struct rte_eth_stats eth_stats; + int ret_code; + uint64_t cnt_bits; + int64_t delta; + const int64_t alpha_percent = 20; + uint64_t values[6]; + + ret_code = rte_eth_stats_get(port_id, ð_stats); + if (ret_code != 0) + return ret_code; + + port_data = &bitrate_data->port_stats[port_id]; + + /* Incoming bitrate. This is an iteratively calculated EWMA + * (Expomentially Weighted Moving Average) that uses a + * weighting factor of alpha_percent. An unsmoothed mean + * for just the current time delta is also calculated for the + * benefit of people who don't understand signal processing. + */ + cnt_bits = (eth_stats.ibytes - port_data->last_ibytes) << 3; + port_data->last_ibytes = eth_stats.ibytes; + if (cnt_bits > port_data->peak_ibits) + port_data->peak_ibits = cnt_bits; + delta = cnt_bits; + delta -= port_data->ewma_ibits; + /* The +-50 fixes integer rounding during divison */ + if (delta > 0) + delta = (delta * alpha_percent + 50) / 100; + else + delta = (delta * alpha_percent - 50) / 100; + port_data->ewma_ibits += delta; + port_data->mean_ibits = cnt_bits; + + /* Outgoing bitrate (also EWMA) */ + cnt_bits = (eth_stats.obytes - port_data->last_obytes) << 3; + port_data->last_obytes = eth_stats.obytes; + if (cnt_bits > port_data->peak_obits) + port_data->peak_obits = cnt_bits; + delta = cnt_bits; + delta -= port_data->ewma_obits; + delta = (delta * alpha_percent + 50) / 100; + port_data->ewma_obits += delta; + port_data->mean_obits = cnt_bits; + + values[0] = port_data->ewma_ibits; + values[1] = port_data->ewma_obits; + values[2] = port_data->mean_ibits; + values[3] = port_data->mean_obits; + values[4] = port_data->peak_ibits; + values[5] = port_data->peak_obits; + rte_metrics_update_values(port_id, bitrate_data->id_stats_set, + values, 6); + return 0; +} diff --git a/lib/librte_bitratestats/rte_bitrate.h b/lib/librte_bitratestats/rte_bitrate.h new file mode 100644 index 0000000..564e4f7 --- /dev/null +++ b/lib/librte_bitratestats/rte_bitrate.h @@ -0,0 +1,80 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016-2017 Intel Corporation. All rights reserved. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +/** + * Bitrate statistics data structure. + * This data structure is intentionally opaque. + */ +struct rte_stats_bitrates; + + +/** + * Allocate a bitrate statistics structure + * + * @return + * - Pointer to structure on success + * - NULL on error (zmalloc failure) + */ +struct rte_stats_bitrates *rte_stats_bitrate_create(void); + + +/** + * Register bitrate statistics with the metric library. + * + * @param bitrate_data + * Pointer allocated by rte_stats_create() + * + * @return + * Zero on success + * Negative on error + */ +int rte_stats_bitrate_reg(struct rte_stats_bitrates *bitrate_data); + + +/** + * Calculate statistics for current time window. The period with which + * this function is called should be the intended sampling window width. + * + * @param bitrate_data + * Bitrate statistics data pointer + * + * @param port_id + * Port id to calculate statistics for + * + * @return + * - Zero on success + * - Negative value on error + */ +int rte_stats_bitrate_calc(struct rte_stats_bitrates *bitrate_data, + uint8_t port_id); diff --git a/lib/librte_bitratestats/rte_bitratestats_version.map b/lib/librte_bitratestats/rte_bitratestats_version.map new file mode 100644 index 0000000..fe74544 --- /dev/null +++ b/lib/librte_bitratestats/rte_bitratestats_version.map @@ -0,0 +1,9 @@ +DPDK_17.05 { + global: + + rte_stats_bitrate_calc; + rte_stats_bitrate_create; + rte_stats_bitrate_reg; + + local: *; +}; diff --git a/mk/rte.app.mk b/mk/rte.app.mk index 98eb052..39c988a 100644 --- a/mk/rte.app.mk +++ b/mk/rte.app.mk @@ -100,6 +100,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_EAL) += -lrte_eal _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE) += -lrte_cmdline _LDLIBS-$(CONFIG_RTE_LIBRTE_REORDER) += -lrte_reorder _LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS) += -lrte_metrics +_LDLIBS-$(CONFIG_RTE_LIBRTE_BITRATE) += -lrte_bitratestats ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),n) -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v11 4/7] app/test-pmd: add bitrate statistics calculation 2017-03-09 16:25 ` [dpdk-dev] [PATCH v11 " Remy Horton ` (2 preceding siblings ...) 2017-03-09 16:25 ` [dpdk-dev] [PATCH v11 3/7] lib: add bitrate statistics library Remy Horton @ 2017-03-09 16:25 ` Remy Horton 2017-03-09 16:25 ` [dpdk-dev] [PATCH v11 5/7] mbuf: add a timestamp to the mbuf for latencystats Remy Horton ` (2 subsequent siblings) 6 siblings, 0 replies; 115+ messages in thread From: Remy Horton @ 2017-03-09 16:25 UTC (permalink / raw) To: dev; +Cc: Thomas Monjalon Calculate bitrate statistics using the bitrate stats library. The resulting statistics can be viewed via proc_info. Signed-off-by: Remy Horton <remy.horton@intel.com> --- app/test-pmd/testpmd.c | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c index bfb2f8e..b31a300 100644 --- a/app/test-pmd/testpmd.c +++ b/app/test-pmd/testpmd.c @@ -1,7 +1,7 @@ /*- * BSD LICENSE * - * Copyright(c) 2010-2016 Intel Corporation. All rights reserved. + * Copyright(c) 2010-2017 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -79,6 +79,10 @@ #include <rte_pdump.h> #endif #include <rte_flow.h> +#include <rte_metrics.h> +#ifdef RTE_LIBRTE_BITRATE +#include <rte_bitrate.h> +#endif #include "testpmd.h" @@ -323,6 +327,9 @@ uint16_t nb_rx_queue_stats_mappings = 0; unsigned max_socket = 0; +/* Bitrate statistics */ +struct rte_stats_bitrates *bitrate_data; + /* Forward function declarations */ static void map_port_queue_stats_mapping_registers(uint8_t pi, struct rte_port *port); static void check_all_ports_link_status(uint32_t port_mask); @@ -922,12 +929,32 @@ run_pkt_fwd_on_lcore(struct fwd_lcore *fc, packet_fwd_t pkt_fwd) struct fwd_stream **fsm; streamid_t nb_fs; streamid_t sm_id; +#ifdef RTE_LIBRTE_BITRATE + uint64_t tics_per_1sec; + uint64_t tics_datum; + uint64_t tics_current; + uint8_t idx_port, cnt_ports; +#endif +#ifdef RTE_LIBRTE_BITRATE + cnt_ports = rte_eth_dev_count(); + tics_datum = rte_rdtsc(); + tics_per_1sec = rte_get_timer_hz(); +#endif fsm = &fwd_streams[fc->stream_idx]; nb_fs = fc->stream_nb; do { for (sm_id = 0; sm_id < nb_fs; sm_id++) (*pkt_fwd)(fsm[sm_id]); +#ifdef RTE_LIBRTE_BITRATE + tics_current = rte_rdtsc(); + if (tics_current - tics_datum >= tics_per_1sec) { + /* Periodic bitrate calculation */ + for (idx_port = 0; idx_port < cnt_ports; idx_port++) + rte_stats_bitrate_calc(bitrate_data, idx_port); + tics_datum = tics_current; + } +#endif } while (! fc->stopped); } @@ -2139,6 +2166,18 @@ main(int argc, char** argv) FOREACH_PORT(port_id, ports) rte_eth_promiscuous_enable(port_id); + /* Init metrics library */ + rte_metrics_init(rte_socket_id()); + + /* Setup bitrate stats */ +#ifdef RTE_LIBRTE_BITRATE + bitrate_data = rte_stats_bitrate_create(); + if (bitrate_data == NULL) + rte_exit(EXIT_FAILURE, "Could not allocate bitrate data.\n"); + rte_stats_bitrate_reg(bitrate_data); +#endif + + #ifdef RTE_LIBRTE_CMDLINE if (interactive == 1) { if (auto_start) { -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v11 5/7] mbuf: add a timestamp to the mbuf for latencystats 2017-03-09 16:25 ` [dpdk-dev] [PATCH v11 " Remy Horton ` (3 preceding siblings ...) 2017-03-09 16:25 ` [dpdk-dev] [PATCH v11 4/7] app/test-pmd: add bitrate statistics calculation Remy Horton @ 2017-03-09 16:25 ` Remy Horton 2017-03-09 19:02 ` Stephen Hemminger 2017-03-09 16:25 ` [dpdk-dev] [PATCH v11 6/7] lib: added new library for latency stats Remy Horton 2017-03-09 16:25 ` [dpdk-dev] [PATCH v11 7/7] app/test-pmd: add latency statistics calculation Remy Horton 6 siblings, 1 reply; 115+ messages in thread From: Remy Horton @ 2017-03-09 16:25 UTC (permalink / raw) To: dev; +Cc: Harry van Haaren, Thomas Monjalon, Reshma Pattan From: Harry van Haaren <harry.van.haaren@intel.com> This commit adds a uint64_t to the mbuf struct, allowing collection of latency and jitter statistics by measuring packet I/O timestamps. This change is required by the latencystats library. Signed-off-by: Reshma Pattan <reshma.pattan@intel.com> Signed-off-by: Harry van Haaren <harry.van.haaren@intel.com> --- lib/librte_mbuf/rte_mbuf.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h index ce57d47..e0dad6e 100644 --- a/lib/librte_mbuf/rte_mbuf.h +++ b/lib/librte_mbuf/rte_mbuf.h @@ -514,6 +514,9 @@ struct rte_mbuf { /** Timesync flags for use with IEEE1588. */ uint16_t timesync; + + /** Timestamp for measuring latency. */ + uint64_t timestamp; } __rte_cache_aligned; /** -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [PATCH v11 5/7] mbuf: add a timestamp to the mbuf for latencystats 2017-03-09 16:25 ` [dpdk-dev] [PATCH v11 5/7] mbuf: add a timestamp to the mbuf for latencystats Remy Horton @ 2017-03-09 19:02 ` Stephen Hemminger 2017-03-10 9:48 ` Van Haaren, Harry 0 siblings, 1 reply; 115+ messages in thread From: Stephen Hemminger @ 2017-03-09 19:02 UTC (permalink / raw) To: Remy Horton; +Cc: dev, Harry van Haaren, Thomas Monjalon, Reshma Pattan On Thu, 9 Mar 2017 16:25:32 +0000 Remy Horton <remy.horton@intel.com> wrote: > From: Harry van Haaren <harry.van.haaren@intel.com> > > This commit adds a uint64_t to the mbuf struct, > allowing collection of latency and jitter statistics > by measuring packet I/O timestamps. This change is > required by the latencystats library. > > Signed-off-by: Reshma Pattan <reshma.pattan@intel.com> > Signed-off-by: Harry van Haaren <harry.van.haaren@intel.com> > --- > lib/librte_mbuf/rte_mbuf.h | 3 +++ > 1 file changed, 3 insertions(+) > > diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h > index ce57d47..e0dad6e 100644 > --- a/lib/librte_mbuf/rte_mbuf.h > +++ b/lib/librte_mbuf/rte_mbuf.h > @@ -514,6 +514,9 @@ struct rte_mbuf { > > /** Timesync flags for use with IEEE1588. */ > uint16_t timesync; > + > + /** Timestamp for measuring latency. */ > + uint64_t timestamp; > } __rte_cache_aligned; > > /** This creates a hole in the mbuf structure, and won't apply to current version of mbuf that has priv_size. ^ permalink raw reply [flat|nested] 115+ messages in thread
* Re: [dpdk-dev] [PATCH v11 5/7] mbuf: add a timestamp to the mbuf for latencystats 2017-03-09 19:02 ` Stephen Hemminger @ 2017-03-10 9:48 ` Van Haaren, Harry 0 siblings, 0 replies; 115+ messages in thread From: Van Haaren, Harry @ 2017-03-10 9:48 UTC (permalink / raw) To: Stephen Hemminger, Horton, Remy; +Cc: dev, Thomas Monjalon, Pattan, Reshma > From: Stephen Hemminger [mailto:stephen@networkplumber.org] > Cc: dev@dpdk.org; Van Haaren, Harry <harry.van.haaren@intel.com>; Thomas Monjalon > <thomas.monjalon@6wind.com>; Pattan, Reshma <reshma.pattan@intel.com> > Subject: Re: [dpdk-dev] [PATCH v11 5/7] mbuf: add a timestamp to the mbuf for > latencystats > > On Thu, 9 Mar 2017 16:25:32 +0000 > Remy Horton <remy.horton@intel.com> wrote: > > > From: Harry van Haaren <harry.van.haaren@intel.com> > > > > This commit adds a uint64_t to the mbuf struct, > > allowing collection of latency and jitter statistics > > by measuring packet I/O timestamps. This change is > > required by the latencystats library. > > > > Signed-off-by: Reshma Pattan <reshma.pattan@intel.com> > > Signed-off-by: Harry van Haaren <harry.van.haaren@intel.com> > > --- > > lib/librte_mbuf/rte_mbuf.h | 3 +++ > > 1 file changed, 3 insertions(+) > > > > diff --git a/lib/librte_mbuf/rte_mbuf.h b/lib/librte_mbuf/rte_mbuf.h > > index ce57d47..e0dad6e 100644 > > --- a/lib/librte_mbuf/rte_mbuf.h > > +++ b/lib/librte_mbuf/rte_mbuf.h > > @@ -514,6 +514,9 @@ struct rte_mbuf { > > > > /** Timesync flags for use with IEEE1588. */ > > uint16_t timesync; > > + > > + /** Timestamp for measuring latency. */ > > + uint64_t timestamp; > > } __rte_cache_aligned; > > > > /** > > This creates a hole in the mbuf structure, and won't apply to current > version of mbuf that has priv_size. This series was previously targeted to 17.02 when the mbuf rework was on the horizon, so placement of the timestamp was not as critical as it is now. Given the mbuf rework[1] is currently in progress, perhaps it is smarter to remove this patch from the patchset and depend on the mbuf rework patchset to add the timestamp instead. The latency stat library should probably also set the new PKT_RX_TIMESTAMP field in the mbuf[2]. [1] mbuf rework http://dpdk.org/dev/patchwork/patch/21601/ [2] mbuf timestamp http://dpdk.org/dev/patchwork/patch/21607/ ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v11 6/7] lib: added new library for latency stats 2017-03-09 16:25 ` [dpdk-dev] [PATCH v11 " Remy Horton ` (4 preceding siblings ...) 2017-03-09 16:25 ` [dpdk-dev] [PATCH v11 5/7] mbuf: add a timestamp to the mbuf for latencystats Remy Horton @ 2017-03-09 16:25 ` Remy Horton 2017-03-09 16:25 ` [dpdk-dev] [PATCH v11 7/7] app/test-pmd: add latency statistics calculation Remy Horton 6 siblings, 0 replies; 115+ messages in thread From: Remy Horton @ 2017-03-09 16:25 UTC (permalink / raw) To: dev; +Cc: Harry van Haaren, Thomas Monjalon, Reshma Pattan From: Harry van Haaren <harry.van.haaren@intel.com> Add a library designed to calculate latency statistics and report them to the application when queried. The library measures minimum, average and maximum latencies, and jitter in nano seconds. The current implementation supports global latency stats, i.e. per application stats. Signed-off-by: Reshma Pattan <reshma.pattan@intel.com> Signed-off-by: Remy Horton <remy.horton@intel.com> Signed-off-by: Harry van Haaren <harry.van.haaren@intel.com> --- MAINTAINERS | 4 + config/common_base | 5 + doc/api/doxy-api-index.md | 1 + doc/api/doxy-api.conf | 1 + doc/guides/prog_guide/metrics_lib.rst | 58 +++- doc/guides/rel_notes/release_17_02.rst | 1 + doc/guides/rel_notes/release_17_05.rst | 5 + lib/Makefile | 1 + lib/librte_latencystats/Makefile | 56 ++++ lib/librte_latencystats/rte_latencystats.c | 366 +++++++++++++++++++++ lib/librte_latencystats/rte_latencystats.h | 154 +++++++++ .../rte_latencystats_version.map | 11 + mk/rte.app.mk | 2 +- 13 files changed, 662 insertions(+), 3 deletions(-) create mode 100644 lib/librte_latencystats/Makefile create mode 100644 lib/librte_latencystats/rte_latencystats.c create mode 100644 lib/librte_latencystats/rte_latencystats.h create mode 100644 lib/librte_latencystats/rte_latencystats_version.map diff --git a/MAINTAINERS b/MAINTAINERS index 8abf4fd..0dc95f5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -643,6 +643,10 @@ Bit-rate statistica M: Remy Horton <remy.horton@intel.com> F: lib/librte_bitratestats/ +Latency Stats +M: Reshma Pattan <reshma.pattan@intel.com> +F: lib/librte_latencystats/ + Test Applications ----------------- diff --git a/config/common_base b/config/common_base index d700ee0..9d7bddf 100644 --- a/config/common_base +++ b/config/common_base @@ -635,3 +635,8 @@ CONFIG_RTE_APP_CRYPTO_PERF=y # Compile the bitrate statistics library # CONFIG_RTE_LIBRTE_BITRATE=y + +# +# Compile the latency statistics library +# +CONFIG_RTE_LIBRTE_LATENCY_STATS=y diff --git a/doc/api/doxy-api-index.md b/doc/api/doxy-api-index.md index 8492bce..9d1818c 100644 --- a/doc/api/doxy-api-index.md +++ b/doc/api/doxy-api-index.md @@ -158,4 +158,5 @@ There are many libraries, so their headers may be grouped by topics: [keepalive] (@ref rte_keepalive.h), [device metrics] (@ref rte_metrics.h), [bitrate statistics] (@ref rte_bitrate.h), + [latency statistics] (@ref rte_latencystats.h), [version] (@ref rte_version.h) diff --git a/doc/api/doxy-api.conf b/doc/api/doxy-api.conf index c4b3b68..5babafa 100644 --- a/doc/api/doxy-api.conf +++ b/doc/api/doxy-api.conf @@ -49,6 +49,7 @@ INPUT = doc/api/doxy-api-index.md \ lib/librte_jobstats \ lib/librte_kni \ lib/librte_kvargs \ + lib/librte_latencystats \ lib/librte_lpm \ lib/librte_mbuf \ lib/librte_mempool \ diff --git a/doc/guides/prog_guide/metrics_lib.rst b/doc/guides/prog_guide/metrics_lib.rst index 1c2a28f..702c29d 100644 --- a/doc/guides/prog_guide/metrics_lib.rst +++ b/doc/guides/prog_guide/metrics_lib.rst @@ -201,8 +201,8 @@ statistics can be obtained by querying the metrics library. Initialization ~~~~~~~~~~~~~~ -Before it is used the bit-rate statistics library has to be initialised -by calling ``rte_stats_bitrate_create()``, which will return a bit-rate +Before the library can be used, it has to be initialised by calling +``rte_stats_bitrate_create()``, which will return a bit-rate calculation object. Since the bit-rate library uses the metrics library to report the calculated statistics, the bit-rate library then needs to register the calculated statistics with the metrics library. This is @@ -243,3 +243,57 @@ desired, this function should be called once a second. } /* ... */ } + + +Latency statistics library +-------------------------- + +The latency statistics library calculates the latency of packet +processing by a DPDK application, reporting the minimum, average, +and maximum nano-seconds that packet processing takes, as well as +the jitter in processing delay. These statistics are then reported +via the metrics library using the following names: + + - ``min_latency_ns``: Minimum processing latency (nano-seconds) + - ``avg_latency_ns``: Average processing latency (nano-seconds) + - ``mac_latency_ns``: Maximum processing latency (nano-seconds) + - ``jitter_ns``: Variance in processing latency (nano-seconds) + +Once initialised and clocked at the appropriate frequency, these +statistics can be obtained by querying the metrics library. + +Initialization +~~~~~~~~~~~~~~ + +Before the library can be used, it has to be initialised by calling +``rte_latencystats_init()``. + +.. code-block:: c + + lcoreid_t latencystats_lcore_id = -1; + + int ret = rte_latencystats_init(1, NULL); + if (ret) + rte_exit(EXIT_FAILURE, "Could not allocate latency data.\n"); + + +Triggering statistic updates +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``rte_latencystats_update()`` function needs to be called +periodically so that latency statistics can be updated. + +.. code-block:: c + + if (latencystats_lcore_id == rte_lcore_id()) + rte_latencystats_update(); + +Library shutdown +~~~~~~~~~~~~~~~~ + +When finished, ``rte_latencystats_uninit()`` needs to be called to +de-initialise the latency library. + +.. code-block:: c + + rte_latencystats_uninit(); diff --git a/doc/guides/rel_notes/release_17_02.rst b/doc/guides/rel_notes/release_17_02.rst index 63786df..05764a0 100644 --- a/doc/guides/rel_notes/release_17_02.rst +++ b/doc/guides/rel_notes/release_17_02.rst @@ -365,6 +365,7 @@ The libraries prepended with a plus sign were incremented in this version. librte_jobstats.so.1 librte_kni.so.2 librte_kvargs.so.1 + + librte_latencystats.so.1 librte_lpm.so.2 librte_mbuf.so.2 librte_mempool.so.2 diff --git a/doc/guides/rel_notes/release_17_05.rst b/doc/guides/rel_notes/release_17_05.rst index 83c83b2..7b6791f 100644 --- a/doc/guides/rel_notes/release_17_05.rst +++ b/doc/guides/rel_notes/release_17_05.rst @@ -74,6 +74,11 @@ Resolved Issues A library that can be used to calculate device bit-rates. Calculated bitrates are reported using the metrics library. +* **Added latency stats library.** + + A library that measures packet latency. The collected statistics are jitter + and latency. For latency the minimum, average, and maximum is measured. + EAL ~~~ diff --git a/lib/Makefile b/lib/Makefile index ecc54c0..78cba3e 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -51,6 +51,7 @@ DIRS-$(CONFIG_RTE_LIBRTE_IP_FRAG) += librte_ip_frag DIRS-$(CONFIG_RTE_LIBRTE_JOBSTATS) += librte_jobstats DIRS-$(CONFIG_RTE_LIBRTE_METRICS) += librte_metrics DIRS-$(CONFIG_RTE_LIBRTE_BITRATE) += librte_bitratestats +DIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += librte_latencystats DIRS-$(CONFIG_RTE_LIBRTE_POWER) += librte_power DIRS-$(CONFIG_RTE_LIBRTE_METER) += librte_meter DIRS-$(CONFIG_RTE_LIBRTE_SCHED) += librte_sched diff --git a/lib/librte_latencystats/Makefile b/lib/librte_latencystats/Makefile new file mode 100644 index 0000000..fd145d3 --- /dev/null +++ b/lib/librte_latencystats/Makefile @@ -0,0 +1,56 @@ +# BSD LICENSE +# +# Copyright(c) 2016-2017 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in +# the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Intel Corporation nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +include $(RTE_SDK)/mk/rte.vars.mk + +# library name +LIB = librte_latencystats.a + +CFLAGS += $(WERROR_FLAGS) -I$(SRCDIR) -O3 +LDLIBS += -lm +LDLIBS += -lpthread + +EXPORT_MAP := rte_latencystats_version.map + +LIBABIVER := 1 + +# all source are stored in SRCS-y +SRCS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) := rte_latencystats.c + +# install this header file +SYMLINK-$(CONFIG_RTE_LIBRTE_LATENCY_STATS)-include := rte_latencystats.h + +# this lib depends upon: +DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_mbuf +DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_eal +DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_ether +DEPDIRS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += lib/librte_metrics + +include $(RTE_SDK)/mk/rte.lib.mk diff --git a/lib/librte_latencystats/rte_latencystats.c b/lib/librte_latencystats/rte_latencystats.c new file mode 100644 index 0000000..5334b8b --- /dev/null +++ b/lib/librte_latencystats/rte_latencystats.c @@ -0,0 +1,366 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016-2017 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <unistd.h> +#include <sys/types.h> +#include <stdbool.h> +#include <math.h> + +#include <rte_mbuf.h> +#include <rte_log.h> +#include <rte_cycles.h> +#include <rte_ethdev.h> +#include <rte_metrics.h> +#include <rte_memzone.h> +#include <rte_lcore.h> +#include <rte_timer.h> + +#include "rte_latencystats.h" + +/** Nano seconds per second */ +#define NS_PER_SEC 1E9 + +/** Clock cycles per nano second */ +static uint64_t +latencystat_cycles_per_ns(void) +{ + return rte_get_timer_hz() / NS_PER_SEC; +} + +/* Macros for printing using RTE_LOG */ +#define RTE_LOGTYPE_LATENCY_STATS RTE_LOGTYPE_USER1 + +static const char *MZ_RTE_LATENCY_STATS = "rte_latencystats"; +static int latency_stats_index; +static uint64_t samp_intvl; +static uint64_t timer_tsc; +static uint64_t prev_tsc; + +struct rte_latency_stats { + float min_latency; /**< Minimum latency in nano seconds */ + float avg_latency; /**< Average latency in nano seconds */ + float max_latency; /**< Maximum latency in nano seconds */ + float jitter; /** Latency variation */ +}; + +static struct rte_latency_stats *glob_stats; + +struct rxtx_cbs { + struct rte_eth_rxtx_callback *cb; +}; + +static struct rxtx_cbs rx_cbs[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT]; +static struct rxtx_cbs tx_cbs[RTE_MAX_ETHPORTS][RTE_MAX_QUEUES_PER_PORT]; + +struct latency_stats_nameoff { + char name[RTE_ETH_XSTATS_NAME_SIZE]; + unsigned int offset; +}; + +static const struct latency_stats_nameoff lat_stats_strings[] = { + {"min_latency_ns", offsetof(struct rte_latency_stats, min_latency)}, + {"avg_latency_ns", offsetof(struct rte_latency_stats, avg_latency)}, + {"max_latency_ns", offsetof(struct rte_latency_stats, max_latency)}, + {"jitter_ns", offsetof(struct rte_latency_stats, jitter)}, +}; + +#define NUM_LATENCY_STATS (sizeof(lat_stats_strings) / \ + sizeof(lat_stats_strings[0])) + +int32_t +rte_latencystats_update(void) +{ + unsigned int i; + float *stats_ptr = NULL; + uint64_t values[NUM_LATENCY_STATS] = {0}; + int ret; + + for (i = 0; i < NUM_LATENCY_STATS; i++) { + stats_ptr = RTE_PTR_ADD(glob_stats, + lat_stats_strings[i].offset); + values[i] = (uint64_t)floor((*stats_ptr)/ + latencystat_cycles_per_ns()); + } + + ret = rte_metrics_update_values(RTE_METRICS_GLOBAL, + latency_stats_index, + values, NUM_LATENCY_STATS); + if (ret < 0) + RTE_LOG(INFO, LATENCY_STATS, "Failed to push the stats\n"); + + return ret; +} + +static void +rte_latencystats_fill_values(struct rte_metric_value *values) +{ + unsigned int i; + float *stats_ptr = NULL; + + for (i = 0; i < NUM_LATENCY_STATS; i++) { + stats_ptr = RTE_PTR_ADD(glob_stats, + lat_stats_strings[i].offset); + values[i].key = i; + values[i].value = (uint64_t)floor((*stats_ptr)/ + latencystat_cycles_per_ns()); + } +} + +static uint16_t +add_time_stamps(uint8_t pid __rte_unused, + uint16_t qid __rte_unused, + struct rte_mbuf **pkts, + uint16_t nb_pkts, + uint16_t max_pkts __rte_unused, + void *user_cb __rte_unused) +{ + unsigned int i; + uint64_t diff_tsc, now; + + /* + * For every sample interval, + * time stamp is marked on one received packet. + */ + now = rte_rdtsc(); + for (i = 0; i < nb_pkts; i++) { + diff_tsc = now - prev_tsc; + timer_tsc += diff_tsc; + if (timer_tsc >= samp_intvl) { + /* + * TBD: Mark the timestamp only + * if not already marked by the + * hardware or the PMD. + */ + pkts[i]->timestamp = now; + timer_tsc = 0; + } + prev_tsc = now; + now = rte_rdtsc(); + } + + return nb_pkts; +} + +static uint16_t +calc_latency(uint8_t pid __rte_unused, + uint16_t qid __rte_unused, + struct rte_mbuf **pkts, + uint16_t nb_pkts, + void *_ __rte_unused) +{ + unsigned int i, cnt = 0; + uint64_t now; + float latency[nb_pkts]; + static float prev_latency; + /* + * Alpha represents degree of weighting decrease in EWMA, + * a constant smoothing factor between 0 and 1. The value + * is used below for measuring average latency. + */ + const float alpha = 0.2; + + now = rte_rdtsc(); + for (i = 0; i < nb_pkts; i++) { + if (pkts[i]->timestamp) + latency[cnt++] = now - pkts[i]->timestamp; + } + + for (i = 0; i < cnt; i++) { + /* + * The jitter is calculated as statistical mean of interpacket + * delay variation. The "jitter estimate" is computed by taking + * the absolute values of the ipdv sequence and applying an + * exponential filter with parameter 1/16 to generate the + * estimate. i.e J=J+(|D(i-1,i)|-J)/16. Where J is jitter, + * D(i-1,i) is difference in latency of two consecutive packets + * i-1 and i. + * Reference: Calculated as per RFC 5481, sec 4.1, + * RFC 3393 sec 4.5, RFC 1889 sec. + */ + glob_stats->jitter += (abs(prev_latency - latency[i]) + - glob_stats->jitter)/16; + if (glob_stats->min_latency == 0) + glob_stats->min_latency = latency[i]; + else if (latency[i] < glob_stats->min_latency) + glob_stats->min_latency = latency[i]; + else if (latency[i] > glob_stats->max_latency) + glob_stats->max_latency = latency[i]; + /* + * The average latency is measured using exponential moving + * average, i.e. using EWMA + * https://en.wikipedia.org/wiki/Moving_average + */ + glob_stats->avg_latency += + alpha * (latency[i] - glob_stats->avg_latency); + prev_latency = latency[i]; + } + + return nb_pkts; +} + +int +rte_latencystats_init(uint64_t app_samp_intvl, + rte_latency_stats_flow_type_fn user_cb) +{ + unsigned int i; + uint8_t pid; + uint16_t qid; + struct rxtx_cbs *cbs = NULL; + const uint8_t nb_ports = rte_eth_dev_count(); + const char *ptr_strings[NUM_LATENCY_STATS] = {0}; + const struct rte_memzone *mz = NULL; + const unsigned int flags = 0; + + if (rte_memzone_lookup(MZ_RTE_LATENCY_STATS)) + return -EEXIST; + + /** Allocate stats in shared memory fo multi process support */ + mz = rte_memzone_reserve(MZ_RTE_LATENCY_STATS, sizeof(*glob_stats), + rte_socket_id(), flags); + if (mz == NULL) { + RTE_LOG(ERR, LATENCY_STATS, "Cannot reserve memory: %s:%d\n", + __func__, __LINE__); + return -ENOMEM; + } + + glob_stats = mz->addr; + samp_intvl = app_samp_intvl * latencystat_cycles_per_ns(); + + /** Register latency stats with stats library */ + for (i = 0; i < NUM_LATENCY_STATS; i++) + ptr_strings[i] = lat_stats_strings[i].name; + + latency_stats_index = rte_metrics_reg_names(ptr_strings, + NUM_LATENCY_STATS); + if (latency_stats_index < 0) { + RTE_LOG(DEBUG, LATENCY_STATS, + "Failed to register latency stats names\n"); + return -1; + } + + /** Register Rx/Tx callbacks */ + for (pid = 0; pid < nb_ports; pid++) { + struct rte_eth_dev_info dev_info; + rte_eth_dev_info_get(pid, &dev_info); + for (qid = 0; qid < dev_info.nb_rx_queues; qid++) { + cbs = &rx_cbs[pid][qid]; + cbs->cb = rte_eth_add_first_rx_callback(pid, qid, + add_time_stamps, user_cb); + if (!cbs->cb) + RTE_LOG(INFO, LATENCY_STATS, "Failed to " + "register Rx callback for pid=%d, " + "qid=%d\n", pid, qid); + } + for (qid = 0; qid < dev_info.nb_tx_queues; qid++) { + cbs = &tx_cbs[pid][qid]; + cbs->cb = rte_eth_add_tx_callback(pid, qid, + calc_latency, user_cb); + if (!cbs->cb) + RTE_LOG(INFO, LATENCY_STATS, "Failed to " + "register Tx callback for pid=%d, " + "qid=%d\n", pid, qid); + } + } + return 0; +} + +int +rte_latencystats_uninit(void) +{ + uint8_t pid; + uint16_t qid; + int ret = 0; + struct rxtx_cbs *cbs = NULL; + const uint8_t nb_ports = rte_eth_dev_count(); + + /** De register Rx/Tx callbacks */ + for (pid = 0; pid < nb_ports; pid++) { + struct rte_eth_dev_info dev_info; + rte_eth_dev_info_get(pid, &dev_info); + for (qid = 0; qid < dev_info.nb_rx_queues; qid++) { + cbs = &rx_cbs[pid][qid]; + ret = rte_eth_remove_rx_callback(pid, qid, cbs->cb); + if (ret) + RTE_LOG(INFO, LATENCY_STATS, "failed to " + "remove Rx callback for pid=%d, " + "qid=%d\n", pid, qid); + } + for (qid = 0; qid < dev_info.nb_tx_queues; qid++) { + cbs = &tx_cbs[pid][qid]; + ret = rte_eth_remove_tx_callback(pid, qid, cbs->cb); + if (ret) + RTE_LOG(INFO, LATENCY_STATS, "failed to " + "remove Tx callback for pid=%d, " + "qid=%d\n", pid, qid); + } + } + + return 0; +} + +int +rte_latencystats_get_names(struct rte_metric_name *names, uint16_t size) +{ + unsigned int i; + + if (names == NULL || size < NUM_LATENCY_STATS) + return NUM_LATENCY_STATS; + + for (i = 0; i < NUM_LATENCY_STATS; i++) + snprintf(names[i].name, sizeof(names[i].name), + "%s", lat_stats_strings[i].name); + + return NUM_LATENCY_STATS; +} + +int +rte_latencystats_get(struct rte_metric_value *values, uint16_t size) +{ + if (size < NUM_LATENCY_STATS || values == NULL) + return NUM_LATENCY_STATS; + + if (rte_eal_process_type() == RTE_PROC_SECONDARY) { + const struct rte_memzone *mz; + mz = rte_memzone_lookup(MZ_RTE_LATENCY_STATS); + if (mz == NULL) { + RTE_LOG(ERR, LATENCY_STATS, + "Latency stats memzone not found\n"); + return -ENOMEM; + } + glob_stats = mz->addr; + } + + /* Retrieve latency stats */ + rte_latencystats_fill_values(values); + + return NUM_LATENCY_STATS; +} diff --git a/lib/librte_latencystats/rte_latencystats.h b/lib/librte_latencystats/rte_latencystats.h new file mode 100644 index 0000000..28c6dcf --- /dev/null +++ b/lib/librte_latencystats/rte_latencystats.h @@ -0,0 +1,154 @@ +/*- + * BSD LICENSE + * + * Copyright(c) 2016-2017 Intel Corporation. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Intel Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _RTE_LATENCYSTATS_H_ +#define _RTE_LATENCYSTATS_H_ + +/** + * @file + * RTE latency stats + * + * library to provide application and flow based latency stats. + */ + +#include <rte_metrics.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Note: This function pointer is for future flow based latency stats + * implementation. + * + * Function type used for identifting flow types of a Rx packet. + * + * The callback function is called on Rx for each packet. + * This function is used for flow based latency calculations. + * + * @param pkt + * Packet that has to be identified with its flow types. + * @param user_param + * The arbitrary user parameter passed in by the application when + * the callback was originally configured. + * @return + * The flow_mask, representing the multiple flow types of a packet. + */ +typedef uint16_t (*rte_latency_stats_flow_type_fn)(struct rte_mbuf *pkt, + void *user_param); + +/** + * Registers Rx/Tx callbacks for each active port, queue. + * + * @param samp_intvl + * Sampling time period in nano seconds, at which packet + * should be marked with time stamp. + * @param user_cb + * Note: This param is for future flow based latency stats + * implementation. + * User callback to be called to get flow types of a packet. + * Used for flow based latency calculation. + * If the value is NULL, global stats will be calculated, + * else flow based latency stats will be calculated. + * For now just pass on the NULL value to this param. + * @return + * -1 : On error + * -ENOMEM: On error + * 0 : On success + */ +int rte_latencystats_init(uint64_t samp_intvl, + rte_latency_stats_flow_type_fn user_cb); + +/** + * Calculates the latency and jitter values internally, exposing the updated + * values via *rte_latencystats_get* or the rte_metrics API. + * @return: + * 0 : on Success + * < 0 : Error in updating values. + */ +int32_t rte_latencystats_update(void); + +/** + * Removes registered Rx/Tx callbacks for each active port, queue. + * + * @return + * -1: On error + * 0: On success + */ +int rte_latencystats_uninit(void); + +/** + * Retrieve names of latency statistics + * + * @param names + * Block of memory to insert names into. Must be at least size in capacity. + * If set to NULL, function returns required capacity. + * @param size + * Capacity of latency stats names (number of names). + * @return + * - positive value lower or equal to size: success. The return value + * is the number of entries filled in the stats table. + * - positive value higher than size: error, the given statistics table + * is too small. The return value corresponds to the size that should + * be given to succeed. The entries in the table are not valid and + * shall not be used by the caller. + */ +int rte_latencystats_get_names(struct rte_metric_name *names, + uint16_t size); + +/** + * Retrieve latency statistics. + * + * @param values + * A pointer to a table of structure of type *rte_metric_value* + * to be filled with latency statistics ids and values. + * This parameter can be set to NULL if size is 0. + * @param size + * The size of the stats table, which should be large enough to store + * all the latency stats. + * @return + * - positive value lower or equal to size: success. The return value + * is the number of entries filled in the stats table. + * - positive value higher than size: error, the given statistics table + * is too small. The return value corresponds to the size that should + * be given to succeed. The entries in the table are not valid and + * shall not be used by the caller. + * -ENOMEM: On failure. + */ +int rte_latencystats_get(struct rte_metric_value *values, + uint16_t size); + +#ifdef __cplusplus +} +#endif + +#endif /* _RTE_LATENCYSTATS_H_ */ diff --git a/lib/librte_latencystats/rte_latencystats_version.map b/lib/librte_latencystats/rte_latencystats_version.map new file mode 100644 index 0000000..ac8403e --- /dev/null +++ b/lib/librte_latencystats/rte_latencystats_version.map @@ -0,0 +1,11 @@ +DPDK_17.05 { + global: + + rte_latencystats_get; + rte_latencystats_get_names; + rte_latencystats_init; + rte_latencystats_uninit; + rte_latencystats_update; + + local: *; +}; diff --git a/mk/rte.app.mk b/mk/rte.app.mk index 39c988a..4dfb413 100644 --- a/mk/rte.app.mk +++ b/mk/rte.app.mk @@ -101,7 +101,7 @@ _LDLIBS-$(CONFIG_RTE_LIBRTE_CMDLINE) += -lrte_cmdline _LDLIBS-$(CONFIG_RTE_LIBRTE_REORDER) += -lrte_reorder _LDLIBS-$(CONFIG_RTE_LIBRTE_METRICS) += -lrte_metrics _LDLIBS-$(CONFIG_RTE_LIBRTE_BITRATE) += -lrte_bitratestats - +_LDLIBS-$(CONFIG_RTE_LIBRTE_LATENCY_STATS) += -lrte_latencystats ifeq ($(CONFIG_RTE_BUILD_SHARED_LIB),n) # plugins (link only if static libraries) -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
* [dpdk-dev] [PATCH v11 7/7] app/test-pmd: add latency statistics calculation 2017-03-09 16:25 ` [dpdk-dev] [PATCH v11 " Remy Horton ` (5 preceding siblings ...) 2017-03-09 16:25 ` [dpdk-dev] [PATCH v11 6/7] lib: added new library for latency stats Remy Horton @ 2017-03-09 16:25 ` Remy Horton 6 siblings, 0 replies; 115+ messages in thread From: Remy Horton @ 2017-03-09 16:25 UTC (permalink / raw) To: dev; +Cc: Harry van Haaren, Thomas Monjalon, Reshma Pattan From: Harry van Haaren <harry.van.haaren@intel.com> This patch adds latency stats commandline argument to testpmd, allowing to specify the lcore to use for latencystats updates. Signed-off-by: Reshma Pattan <reshma.pattan@intel.com> Signed-off-by: Harry van Haaren <harry.van.haaren@intel.com> Signed-off-by: Remy Horton <remy.horton@intel.com> --- app/test-pmd/parameters.c | 20 +++++++++++++++++++- app/test-pmd/testpmd.c | 37 +++++++++++++++++++++++++++++++++++++ app/test-pmd/testpmd.h | 6 +++++- 3 files changed, 61 insertions(+), 2 deletions(-) diff --git a/app/test-pmd/parameters.c b/app/test-pmd/parameters.c index 28db8cd..30b60ba 100644 --- a/app/test-pmd/parameters.c +++ b/app/test-pmd/parameters.c @@ -1,7 +1,7 @@ /*- * BSD LICENSE * - * Copyright(c) 2010-2016 Intel Corporation. All rights reserved. + * Copyright(c) 2010-2017 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -149,6 +149,10 @@ usage(char* progname) "the packet will be enqueued into the rx drop-queue. " "If the drop-queue doesn't exist, the packet is dropped. " "By default drop-queue=127.\n"); +#ifdef RTE_LIBRTE_LATENCY_STATS + printf(" --latencystats=N: enable latency and jitter statistcs " + "monitoring on lcore id N.\n"); +#endif printf(" --crc-strip: enable CRC stripping by hardware.\n"); printf(" --enable-lro: enable large receive offload.\n"); printf(" --enable-rx-cksum: enable rx hardware checksum offload.\n"); @@ -526,6 +530,7 @@ launch_args_parse(int argc, char** argv) { "pkt-filter-report-hash", 1, 0, 0 }, { "pkt-filter-size", 1, 0, 0 }, { "pkt-filter-drop-queue", 1, 0, 0 }, + { "latencystats", 1, 0, 0 }, { "crc-strip", 0, 0, 0 }, { "enable-lro", 0, 0, 0 }, { "enable-rx-cksum", 0, 0, 0 }, @@ -766,6 +771,19 @@ launch_args_parse(int argc, char** argv) "drop queue %d invalid - must" "be >= 0 \n", n); } +#ifdef RTE_LIBRTE_LATENCY_STATS + if (!strcmp(lgopts[opt_idx].name, + "latencystats")) { + n = atoi(optarg); + if (n >= 0) { + latencystats_lcore_id = (lcoreid_t) n; + latencystats_enabled = 1; + } else + rte_exit(EXIT_FAILURE, + "invalid lcore id %d for latencystats" + " must be >= 0\n", n); + } +#endif if (!strcmp(lgopts[opt_idx].name, "crc-strip")) rx_mode.hw_strip_crc = 1; if (!strcmp(lgopts[opt_idx].name, "enable-lro")) diff --git a/app/test-pmd/testpmd.c b/app/test-pmd/testpmd.c index b31a300..524e758 100644 --- a/app/test-pmd/testpmd.c +++ b/app/test-pmd/testpmd.c @@ -83,6 +83,10 @@ #ifdef RTE_LIBRTE_BITRATE #include <rte_bitrate.h> #endif +#include <rte_metrics.h> +#ifdef RTE_LIBRTE_LATENCY_STATS +#include <rte_latencystats.h> +#endif #include "testpmd.h" @@ -276,6 +280,20 @@ uint32_t bypass_timeout = RTE_BYPASS_TMT_OFF; #endif +#ifdef RTE_LIBRTE_LATENCY_STATS + +/* + * Set when latency stats is enabled in the commandline + */ +uint8_t latencystats_enabled; + +/* + * Lcore ID to serive latency statistics. + */ +lcoreid_t latencystats_lcore_id = -1; + +#endif + /* * Ethernet device configuration. */ @@ -955,6 +973,11 @@ run_pkt_fwd_on_lcore(struct fwd_lcore *fc, packet_fwd_t pkt_fwd) tics_datum = tics_current; } #endif +#ifdef RTE_LIBRTE_LATENCY_STATS + if (latencystats_lcore_id == rte_lcore_id()) + rte_latencystats_update(); +#endif + } while (! fc->stopped); } @@ -2108,6 +2131,9 @@ signal_handler(int signum) /* uninitialize packet capture framework */ rte_pdump_uninit(); #endif +#ifdef RTE_LIBRTE_LATENCY_STATS + rte_latencystats_uninit(); +#endif force_quit(); /* exit with the expected status */ signal(signum, SIG_DFL); @@ -2169,6 +2195,17 @@ main(int argc, char** argv) /* Init metrics library */ rte_metrics_init(rte_socket_id()); +#ifdef RTE_LIBRTE_LATENCY_STATS + if (latencystats_enabled != 0) { + int ret = rte_latencystats_init(1, NULL); + if (ret) + printf("Warning: latencystats init()" + " returned error %d\n", ret); + printf("Latencystats running on lcore %d\n", + latencystats_lcore_id); + } +#endif + /* Setup bitrate stats */ #ifdef RTE_LIBRTE_BITRATE bitrate_data = rte_stats_bitrate_create(); diff --git a/app/test-pmd/testpmd.h b/app/test-pmd/testpmd.h index 8cf2860..f0652ee 100644 --- a/app/test-pmd/testpmd.h +++ b/app/test-pmd/testpmd.h @@ -1,7 +1,7 @@ /*- * BSD LICENSE * - * Copyright(c) 2010-2016 Intel Corporation. All rights reserved. + * Copyright(c) 2010-2017 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -381,6 +381,10 @@ extern enum dcb_queue_mapping_mode dcb_q_mapping; extern uint16_t mbuf_data_size; /**< Mbuf data space size. */ extern uint32_t param_total_num_mbufs; + +extern uint8_t latencystats_enabled; +extern lcoreid_t latencystats_lcore_id; + extern struct rte_fdir_conf fdir_conf; /* -- 2.5.5 ^ permalink raw reply [flat|nested] 115+ messages in thread
end of thread, other threads:[~2017-03-10 9:48 UTC | newest] Thread overview: 115+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2016-08-24 14:58 [dpdk-dev] [RFC PATCH v1] rte: add bit-rate metrics to xstats Remy Horton 2016-08-26 13:28 ` Pattan, Reshma 2016-08-29 10:01 ` Pattan, Reshma 2016-08-29 11:19 ` Remy Horton 2016-10-28 1:04 ` [dpdk-dev] [PATCH v2 0/3] expanded statistic reporting Remy Horton 2016-10-28 1:04 ` [dpdk-dev] [RFC PATCH v2 1/3] lib: add information metrics library Remy Horton 2016-10-28 1:04 ` [dpdk-dev] [RFC PATCH v2 2/3] lib: add bitrate statistics library Remy Horton 2016-10-28 1:12 ` Stephen Hemminger 2016-10-28 7:48 ` Remy Horton 2016-10-28 7:39 ` Morten Brørup 2016-11-01 1:53 ` Remy Horton 2016-10-28 1:04 ` [dpdk-dev] [RFC PATCH v2 3/3] app/test-pmd: add support for bitrate statistics Remy Horton 2016-11-04 3:36 ` [dpdk-dev] [PATCH v3 0/3] Expanded statistics reporting Remy Horton 2016-11-04 3:36 ` [dpdk-dev] [PATCH v3 1/3] lib: add information metrics library Remy Horton 2016-11-04 16:42 ` Pattan, Reshma 2016-11-07 15:25 ` Pattan, Reshma 2016-11-08 3:19 ` Remy Horton 2016-11-04 3:36 ` [dpdk-dev] [PATCH v3 2/3] lib: add bitrate statistics library Remy Horton 2016-11-04 3:36 ` [dpdk-dev] [PATCH v3 3/3] app/test-pmd: add support for bitrate statistics Remy Horton 2016-11-15 7:15 ` [dpdk-dev] [PATCH v4 0/3] Expanded statistics reporting Remy Horton 2016-11-15 7:15 ` [dpdk-dev] [PATCH v4 1/3] lib: add information metrics library Remy Horton 2016-11-15 7:15 ` [dpdk-dev] [PATCH v4 2/3] lib: add bitrate statistics library Remy Horton 2016-11-15 15:17 ` Pattan, Reshma 2016-11-15 7:15 ` [dpdk-dev] [PATCH v4 3/3] app/test-pmd: add support for bitrate statistics Remy Horton 2016-11-18 8:00 ` [dpdk-dev] [PATCH v5 0/4] Expanded statistics reporting Remy Horton 2016-11-18 8:00 ` [dpdk-dev] [PATCH v5 1/4] lib: add information metrics library Remy Horton 2016-11-18 8:00 ` [dpdk-dev] [PATCH v5 2/4] lib: add bitrate statistics library Remy Horton 2016-11-18 8:00 ` [dpdk-dev] [PATCH v5 3/4] app/test-pmd: add support for bitrate statistics Remy Horton 2016-11-18 8:00 ` [dpdk-dev] [PATCH v5 4/4] latencystats: added new library for latency stats Remy Horton 2017-01-11 16:03 ` [dpdk-dev] [PATCH v6 0/4] Expanded statistics reporting Remy Horton 2017-01-11 16:03 ` [dpdk-dev] [PATCH v6 1/4] lib: add information metrics library Remy Horton 2017-01-12 13:22 ` Thomas Monjalon 2017-01-12 15:30 ` Remy Horton 2017-01-12 19:05 ` Thomas Monjalon 2017-01-16 10:27 ` Remy Horton 2017-01-11 16:03 ` [dpdk-dev] [PATCH v6 2/4] lib: add bitrate statistics library Remy Horton 2017-01-11 16:15 ` Stephen Hemminger 2017-01-16 13:18 ` Remy Horton 2017-01-11 16:03 ` [dpdk-dev] [PATCH v6 3/4] app/test-pmd: add support for bitrate statistics Remy Horton 2017-01-12 13:32 ` Thomas Monjalon 2017-01-11 16:03 ` [dpdk-dev] [PATCH v6 4/4] latencystats: added new library for latency stats Remy Horton 2017-01-12 13:41 ` Thomas Monjalon 2017-01-12 14:44 ` Remy Horton 2017-01-13 9:45 ` Mcnamara, John 2017-01-13 9:53 ` Thomas Monjalon 2017-01-16 16:18 ` Mcnamara, John 2017-01-11 16:58 ` [dpdk-dev] [PATCH v6 0/4] Expanded statistics reporting Thomas Monjalon 2017-01-16 16:19 ` [dpdk-dev] [PATCH v7 0/6] " Remy Horton 2017-01-16 16:19 ` [dpdk-dev] [PATCH v7 1/6] lib: add information metrics library Remy Horton 2017-01-17 11:01 ` Van Haaren, Harry 2017-01-17 13:40 ` Remy Horton 2017-01-17 14:23 ` Van Haaren, Harry 2017-01-16 16:19 ` [dpdk-dev] [PATCH v7 2/6] app/proc_info: add metrics displaying Remy Horton 2017-01-17 11:08 ` Van Haaren, Harry 2017-01-17 14:27 ` Remy Horton 2017-01-16 16:19 ` [dpdk-dev] [PATCH v7 3/6] lib: add bitrate statistics library Remy Horton 2017-01-17 11:16 ` Van Haaren, Harry 2017-01-17 15:37 ` Remy Horton 2017-01-16 16:19 ` [dpdk-dev] [PATCH v7 4/6] app/test-pmd: add bitrate statistics calculation Remy Horton 2017-01-17 11:19 ` Van Haaren, Harry 2017-01-16 16:19 ` [dpdk-dev] [PATCH v7 5/6] lib: added new library for latency stats Remy Horton 2017-01-17 4:29 ` Jerin Jacob 2017-01-17 6:48 ` Remy Horton 2017-01-17 7:35 ` Jerin Jacob 2017-01-17 11:19 ` Mcnamara, John 2017-01-17 12:34 ` Jerin Jacob 2017-01-17 14:53 ` Mcnamara, John 2017-01-17 16:25 ` Jerin Jacob 2017-01-18 20:11 ` Olivier Matz 2017-01-24 15:24 ` Olivier MATZ 2017-01-17 11:41 ` Van Haaren, Harry 2017-01-16 16:19 ` [dpdk-dev] [PATCH v7 6/6] app/test-pmd: add latency statistics calculation Remy Horton 2017-01-17 11:45 ` Van Haaren, Harry 2017-01-17 23:24 ` [dpdk-dev] [PATCH v8 0/7] Expanded statistics reporting Remy Horton 2017-01-17 23:24 ` [dpdk-dev] [PATCH v8 1/7] lib: add information metrics library Remy Horton 2017-01-17 23:24 ` [dpdk-dev] [PATCH v8 2/7] app/proc_info: add metrics displaying Remy Horton 2017-01-17 23:24 ` [dpdk-dev] [PATCH v8 3/7] lib: add bitrate statistics library Remy Horton 2017-01-17 23:24 ` [dpdk-dev] [PATCH v8 4/7] app/test-pmd: add bitrate statistics calculation Remy Horton 2017-01-17 23:24 ` [dpdk-dev] [PATCH v8 5/7] mbuf: add a timestamp to the mbuf for latencystats Remy Horton 2017-01-17 23:24 ` [dpdk-dev] [PATCH v8 6/7] lib: added new library for latency stats Remy Horton 2017-01-17 23:24 ` [dpdk-dev] [PATCH v8 7/7] app/test-pmd: add latency statistics calculation Remy Horton 2017-01-18 15:05 ` [dpdk-dev] [PATCH v9 0/7] Expanded statistics reporting Remy Horton 2017-01-18 15:05 ` [dpdk-dev] [PATCH v9 1/7] lib: add information metrics library Remy Horton 2017-01-30 15:50 ` Thomas Monjalon 2017-01-30 21:44 ` Remy Horton 2017-01-31 13:13 ` Mcnamara, John 2017-01-31 13:28 ` Bruce Richardson 2017-02-02 17:22 ` Thomas Monjalon 2017-01-18 15:05 ` [dpdk-dev] [PATCH v9 2/7] app/proc_info: add metrics displaying Remy Horton 2017-01-18 15:05 ` [dpdk-dev] [PATCH v9 3/7] lib: add bitrate statistics library Remy Horton 2017-01-18 15:05 ` [dpdk-dev] [PATCH v9 4/7] app/test-pmd: add bitrate statistics calculation Remy Horton 2017-01-18 15:05 ` [dpdk-dev] [PATCH v9 5/7] mbuf: add a timestamp to the mbuf for latencystats Remy Horton 2017-01-18 15:05 ` [dpdk-dev] [PATCH v9 6/7] lib: added new library for latency stats Remy Horton 2017-01-18 15:05 ` [dpdk-dev] [PATCH v9 7/7] app/test-pmd: add latency statistics calculation Remy Horton 2017-02-03 10:33 ` [dpdk-dev] [PATCH v10 0/7] Expanded statistics reporting Remy Horton 2017-02-03 10:33 ` [dpdk-dev] [PATCH v10 1/7] lib: add information metrics library Remy Horton 2017-02-03 10:33 ` [dpdk-dev] [PATCH v10 2/7] app/proc_info: add metrics displaying Remy Horton 2017-02-03 10:33 ` [dpdk-dev] [PATCH v10 3/7] lib: add bitrate statistics library Remy Horton 2017-02-03 10:33 ` [dpdk-dev] [PATCH v10 4/7] app/test-pmd: add bitrate statistics calculation Remy Horton 2017-02-03 10:33 ` [dpdk-dev] [PATCH v10 5/7] mbuf: add a timestamp to the mbuf for latencystats Remy Horton 2017-02-03 10:33 ` [dpdk-dev] [PATCH v10 6/7] lib: added new library for latency stats Remy Horton 2017-02-03 10:33 ` [dpdk-dev] [PATCH v10 7/7] app/test-pmd: add latency statistics calculation Remy Horton 2017-02-16 10:53 ` [dpdk-dev] [PATCH v10 0/7] Expanded statistics reporting Thomas Monjalon 2017-02-23 7:09 ` Remy Horton 2017-02-23 8:45 ` Thomas Monjalon 2017-03-09 16:25 ` [dpdk-dev] [PATCH v11 " Remy Horton 2017-03-09 16:25 ` [dpdk-dev] [PATCH v11 1/7] lib: add information metrics library Remy Horton 2017-03-09 16:25 ` [dpdk-dev] [PATCH v11 2/7] app/proc_info: add metrics displaying Remy Horton 2017-03-09 16:25 ` [dpdk-dev] [PATCH v11 3/7] lib: add bitrate statistics library Remy Horton 2017-03-09 16:25 ` [dpdk-dev] [PATCH v11 4/7] app/test-pmd: add bitrate statistics calculation Remy Horton 2017-03-09 16:25 ` [dpdk-dev] [PATCH v11 5/7] mbuf: add a timestamp to the mbuf for latencystats Remy Horton 2017-03-09 19:02 ` Stephen Hemminger 2017-03-10 9:48 ` Van Haaren, Harry 2017-03-09 16:25 ` [dpdk-dev] [PATCH v11 6/7] lib: added new library for latency stats Remy Horton 2017-03-09 16:25 ` [dpdk-dev] [PATCH v11 7/7] app/test-pmd: add latency statistics calculation Remy Horton
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).