From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga06.intel.com (mga06.intel.com [134.134.136.31]) by dpdk.org (Postfix) with ESMTP id 3EC695320 for ; Wed, 24 Aug 2016 16:58:05 +0200 (CEST) Received: from fmsmga004.fm.intel.com ([10.253.24.48]) by orsmga104.jf.intel.com with ESMTP; 24 Aug 2016 07:58:04 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.28,571,1464678000"; d="scan'208";a="160357303" Received: from rhorton-mobl.ger.corp.intel.com (HELO VM.ir.intel.com) ([163.33.230.22]) by fmsmga004.fm.intel.com with ESMTP; 24 Aug 2016 07:58:03 -0700 From: Remy Horton To: thomas.monjalon@6wind.com Cc: dev@dpdk.org Date: Wed, 24 Aug 2016 15:58:02 +0100 Message-Id: <1472050682-21420-1-git-send-email-remy.horton@intel.com> X-Mailer: git-send-email 2.5.5 Subject: [dpdk-dev] [RFC PATCH v1] rte: add bit-rate metrics to xstats X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 24 Aug 2016 14:58:05 -0000 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 --- 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