All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCH v1 0/3] Remove string operations from xstats
@ 2016-04-15 14:44 Remy Horton
  2016-04-15 14:44 ` [RFC PATCH v1 1/3] rte: change xstats to use integer keys Remy Horton
                   ` (5 more replies)
  0 siblings, 6 replies; 71+ messages in thread
From: Remy Horton @ 2016-04-15 14:44 UTC (permalink / raw)
  To: dev

The current extended ethernet statistics fetching involve doing several
string operations, which causes performance issues if there are lots of
statistics and/or network interfaces. This RFC patchset changes the API
for xstats to use integer identifiers instead of strings and implements
this new API for the ixgbe driver. Others drivers to follow.

--

Since this will involve API & ABI breakage as previously advertised,
there are several design assumptions that need consideration:

*) id-name & id-value pairs for both lookup and query
Permits out-of-order and non-contigious returning of names/ids/values,
even though expected implmentations would in practice return items in
sorted order by id. Is this sufficent/desirable future proofing? Idea
is to allow possibility of drivers returning partial statistics.

*) Bulk name-id mapping lookup only
At the moment individual lookup is not supported, as this would impose
extra overheads on drivers. The assumption is that any end user would
fetch all this data once on startup and then cache the mappings.

*) Replacement or additional API
This patch replaces the current xstats API, but there is no inherant
reason beyond maintainability why this funtionality could not be in
addition rather than a replacement. What is consensus on this?

Comments welcome.

Remy Horton (3):
  rte: change xstats to use integer keys
  drivers/net/ixgbe: change xstats to use integer keys
  examples/ethtool: add xstats display command

 drivers/net/ixgbe/ixgbe_ethdev.c      | 87 +++++++++++++++++++++++++++++++----
 examples/ethtool/ethtool-app/ethapp.c | 57 +++++++++++++++++++++++
 lib/librte_ether/rte_ethdev.c         | 87 +++++++++++++++++++++++++++++++----
 lib/librte_ether/rte_ethdev.h         | 38 +++++++++++++++
 4 files changed, 252 insertions(+), 17 deletions(-)

-- 
2.5.5

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

* [RFC PATCH v1 1/3] rte: change xstats to use integer keys
  2016-04-15 14:44 [RFC PATCH v1 0/3] Remove string operations from xstats Remy Horton
@ 2016-04-15 14:44 ` Remy Horton
  2016-04-29 13:17   ` David Harton (dharton)
  2016-04-15 14:44 ` [RFC PATCH v1 2/3] drivers/net/ixgbe: change xstats to use integers Remy Horton
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 71+ messages in thread
From: Remy Horton @ 2016-04-15 14:44 UTC (permalink / raw)
  To: dev, Thomas Monjalon

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 lib/librte_ether/rte_ethdev.c | 87 +++++++++++++++++++++++++++++++++++++++----
 lib/librte_ether/rte_ethdev.h | 38 +++++++++++++++++++
 2 files changed, 117 insertions(+), 8 deletions(-)

diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index a31018e..cdd0685 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -1507,6 +1507,82 @@ rte_eth_stats_reset(uint8_t port_id)
 	dev->data->rx_mbuf_alloc_failed = 0;
 }
 
+static int
+rte_eth_xstats_count(uint8_t port_id)
+{
+	struct rte_eth_dev *dev;
+	int count;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL);
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->xstats_names, -ENOTSUP);
+	count = (*dev->dev_ops->xstats_names)(dev, NULL, 0);
+	if (count >= 0) {
+		count += RTE_NB_STATS;
+		count += dev->data->nb_rx_queues * RTE_NB_RXQ_STATS;
+		count += dev->data->nb_tx_queues * RTE_NB_TXQ_STATS;
+	}
+	return count;
+}
+
+int
+rte_eth_xstats_names(uint8_t port_id, struct rte_eth_xstats_name *ptr_names,
+	unsigned limit)
+{
+	struct rte_eth_dev *dev;
+	int cnt_used_entries;
+	int cnt_expected_entries;
+	uint32_t idx, id_queue;
+	int offset;
+
+	cnt_expected_entries = rte_eth_xstats_count(port_id);
+	if (cnt_expected_entries < 0 || ptr_names == NULL)
+		return cnt_expected_entries;
+
+	if ((int)limit < cnt_expected_entries)
+		return -ERANGE;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL);
+	dev = &rte_eth_devices[port_id];
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->xstats_names, -ENOTSUP);
+	cnt_used_entries = (*dev->dev_ops->xstats_names)(
+		dev, ptr_names, limit);
+
+	if (cnt_used_entries < 0)
+		return cnt_used_entries;
+
+	offset = cnt_used_entries * RTE_ETH_XSTATS_NAME_SIZE;
+	for (idx = 0; idx < RTE_NB_STATS; idx++) {
+		snprintf(ptr_names[cnt_used_entries].name,
+			sizeof(ptr_names[0].name),
+			"%s", rte_stats_strings[idx].name);
+		offset += RTE_ETH_XSTATS_NAME_SIZE;
+		cnt_used_entries++;
+	}
+	for (id_queue = 0; id_queue < dev->data->nb_rx_queues; id_queue++) {
+		for (idx = 0; idx < RTE_NB_RXQ_STATS; idx++) {
+			snprintf(ptr_names[cnt_used_entries].name,
+				sizeof(ptr_names[0].name),
+				"rx_q%u%s",
+				id_queue, rte_rxq_stats_strings[idx].name);
+			offset += RTE_ETH_XSTATS_NAME_SIZE;
+			cnt_used_entries++;
+		}
+
+	}
+	for (id_queue = 0; id_queue < dev->data->nb_tx_queues; id_queue++) {
+		for (idx = 0; idx < RTE_NB_TXQ_STATS; idx++) {
+			snprintf(ptr_names[cnt_used_entries].name,
+				sizeof(ptr_names[0].name),
+				"tx_q%u%s",
+				id_queue, rte_txq_stats_strings[idx].name);
+			offset += RTE_ETH_XSTATS_NAME_SIZE;
+			cnt_used_entries++;
+		}
+	}
+	return cnt_used_entries;
+}
+
 /* retrieve ethdev extended statistics */
 int
 rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
@@ -1551,8 +1627,7 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
 		stats_ptr = RTE_PTR_ADD(&eth_stats,
 					rte_stats_strings[i].offset);
 		val = *stats_ptr;
-		snprintf(xstats[count].name, sizeof(xstats[count].name),
-			"%s", rte_stats_strings[i].name);
+		xstats[count].key = count + xcount;
 		xstats[count++].value = val;
 	}
 
@@ -1563,9 +1638,7 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
 					rte_rxq_stats_strings[i].offset +
 					q * sizeof(uint64_t));
 			val = *stats_ptr;
-			snprintf(xstats[count].name, sizeof(xstats[count].name),
-				"rx_q%u_%s", q,
-				rte_rxq_stats_strings[i].name);
+			xstats[count].key = count + xcount;
 			xstats[count++].value = val;
 		}
 	}
@@ -1577,9 +1650,7 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
 					rte_txq_stats_strings[i].offset +
 					q * sizeof(uint64_t));
 			val = *stats_ptr;
-			snprintf(xstats[count].name, sizeof(xstats[count].name),
-				"tx_q%u_%s", q,
-				rte_txq_stats_strings[i].name);
+			xstats[count].key = count + xcount;
 			xstats[count++].value = val;
 		}
 	}
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 022733e..4b81c59 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -941,10 +941,23 @@ struct rte_eth_txq_info {
  * structure.
  */
 struct rte_eth_xstats {
+	/* FIXME: Remove name[] once remaining drivers converted */
 	char name[RTE_ETH_XSTATS_NAME_SIZE];
+	uint64_t key;
 	uint64_t value;
 };
 
+/**
+ * A name-key lookup element for extended statistics.
+ *
+ * This structure is used to map between names and ID numbers
+ * for extended ethernet statistics.
+ */
+struct rte_eth_xstats_name {
+	char name[RTE_ETH_XSTATS_NAME_SIZE];
+	uint64_t id;
+};
+
 #define ETH_DCB_NUM_TCS    8
 #define ETH_MAX_VMDQ_POOL  64
 
@@ -1080,6 +1093,10 @@ typedef int (*eth_xstats_get_t)(struct rte_eth_dev *dev,
 typedef void (*eth_xstats_reset_t)(struct rte_eth_dev *dev);
 /**< @internal Reset extended stats of an Ethernet device. */
 
+typedef int (*eth_xstats_names_t)(struct rte_eth_dev *dev,
+	struct rte_eth_xstats_name *ptr_names, unsigned limit);
+/**< @internal Get names of extended stats of an Ethernet device. */
+
 typedef int (*eth_queue_stats_mapping_set_t)(struct rte_eth_dev *dev,
 					     uint16_t queue_id,
 					     uint8_t stat_idx,
@@ -1427,6 +1444,8 @@ struct eth_dev_ops {
 	eth_stats_reset_t          stats_reset;   /**< Reset generic device statistics. */
 	eth_xstats_get_t           xstats_get;    /**< Get extended device statistics. */
 	eth_xstats_reset_t         xstats_reset;  /**< Reset extended device statistics. */
+	eth_xstats_names_t         xstats_names;
+	/**< Get names of extended statistics. */
 	eth_queue_stats_mapping_set_t queue_stats_mapping_set;
 	/**< Configure per queue stat counter mapping. */
 	eth_dev_infos_get_t        dev_infos_get; /**< Get device info. */
@@ -2279,6 +2298,25 @@ int rte_eth_stats_get(uint8_t port_id, struct rte_eth_stats *stats);
 void rte_eth_stats_reset(uint8_t port_id);
 
 /**
+ * Retrieve names of extended statistics of an Ethernet device.
+ *
+ * Names within ptr_strings will be aligned to RTE_ETH_XSTATS_NAME_SIZE and
+ * will be listed in ascending mapping order.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param ptr_names
+ *  Block of memory to insert names into. Must be at least limit in size.
+ *  If NULL, function returns how many statistics are available.
+ * @param limit
+ *  Capacity of ptr_strings (number of names). Ignored if ptr_string is NULL.
+ * @return
+ *  If successful, number of statistics; negative on error.
+ */
+int rte_eth_xstats_names(uint8_t port_id, struct rte_eth_xstats_name *ptr_names,
+	unsigned limit);
+
+/**
  * Retrieve extended statistics of an Ethernet device.
  *
  * @param port_id
-- 
2.5.5

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

* [RFC PATCH v1 2/3] drivers/net/ixgbe: change xstats to use integers
  2016-04-15 14:44 [RFC PATCH v1 0/3] Remove string operations from xstats Remy Horton
  2016-04-15 14:44 ` [RFC PATCH v1 1/3] rte: change xstats to use integer keys Remy Horton
@ 2016-04-15 14:44 ` Remy Horton
  2016-04-29 13:43   ` David Harton (dharton)
  2016-04-15 14:44 ` [RFC PATCH v1 3/3] examples/ethtool: add xstats display command Remy Horton
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 71+ messages in thread
From: Remy Horton @ 2016-04-15 14:44 UTC (permalink / raw)
  To: dev, Helin Zhang

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 drivers/net/ixgbe/ixgbe_ethdev.c | 87 +++++++++++++++++++++++++++++++++++-----
 1 file changed, 78 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 3f1ebc1..4d31fe9 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -179,6 +179,10 @@ static int ixgbevf_dev_xstats_get(struct rte_eth_dev *dev,
 				  struct rte_eth_xstats *xstats, unsigned n);
 static void ixgbe_dev_stats_reset(struct rte_eth_dev *dev);
 static void ixgbe_dev_xstats_reset(struct rte_eth_dev *dev);
+static int ixgbe_dev_xstats_names(__rte_unused struct rte_eth_dev *dev,
+	struct rte_eth_xstats_name *ptr_names, __rte_unused unsigned limit);
+static int ixgbevf_dev_xstats_names(__rte_unused struct rte_eth_dev *dev,
+	struct rte_eth_xstats_name *ptr_names, __rte_unused unsigned limit);
 static int ixgbe_dev_queue_stats_mapping_set(struct rte_eth_dev *eth_dev,
 					     uint16_t queue_id,
 					     uint8_t stat_idx,
@@ -466,6 +470,7 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = {
 	.xstats_get           = ixgbe_dev_xstats_get,
 	.stats_reset          = ixgbe_dev_stats_reset,
 	.xstats_reset         = ixgbe_dev_xstats_reset,
+	.xstats_names         = ixgbe_dev_xstats_names,
 	.queue_stats_mapping_set = ixgbe_dev_queue_stats_mapping_set,
 	.dev_infos_get        = ixgbe_dev_info_get,
 	.dev_supported_ptypes_get = ixgbe_dev_supported_ptypes_get,
@@ -555,6 +560,7 @@ static const struct eth_dev_ops ixgbevf_eth_dev_ops = {
 	.xstats_get           = ixgbevf_dev_xstats_get,
 	.stats_reset          = ixgbevf_dev_stats_reset,
 	.xstats_reset         = ixgbevf_dev_stats_reset,
+	.xstats_names         = ixgbevf_dev_xstats_names,
 	.dev_close            = ixgbevf_dev_close,
 	.allmulticast_enable  = ixgbevf_dev_allmulticast_enable,
 	.allmulticast_disable = ixgbevf_dev_allmulticast_disable,
@@ -2698,6 +2704,76 @@ ixgbe_xstats_calc_num(void) {
 		(IXGBE_NB_TXQ_PRIO_STATS * 8);
 }
 
+static int ixgbe_dev_xstats_names(__rte_unused struct rte_eth_dev *dev,
+	struct rte_eth_xstats_name *ptr_names, __rte_unused unsigned limit)
+{
+	const unsigned cnt_stats = ixgbe_xstats_calc_num();
+	unsigned stat, i, count, offset;
+
+	if (ptr_names != NULL) {
+		count = 0;
+		offset = 0;
+
+		/* Note: limit >= cnt_stats checked upstream
+		 * in rte_eth_xstats_names()
+		 */
+
+		/* Extended stats from ixgbe_hw_stats */
+		for (i = 0; i < IXGBE_NB_HW_STATS; i++) {
+			snprintf(ptr_names[count].name,
+				sizeof(ptr_names[count].name),
+				"%s",
+				rte_ixgbe_stats_strings[i].name);
+			count++;
+			offset += RTE_ETH_XSTATS_NAME_SIZE;
+		}
+
+		/* RX Priority Stats */
+		for (stat = 0; stat < IXGBE_NB_RXQ_PRIO_STATS; stat++) {
+			for (i = 0; i < 8; i++) {
+				snprintf(ptr_names[count].name,
+					sizeof(ptr_names[count].name),
+					"rx_priority%u_%s", i,
+					rte_ixgbe_rxq_strings[stat].name);
+				count++;
+				offset += RTE_ETH_XSTATS_NAME_SIZE;
+			}
+		}
+
+		/* TX Priority Stats */
+		for (stat = 0; stat < IXGBE_NB_TXQ_PRIO_STATS; stat++) {
+			for (i = 0; i < 8; i++) {
+				snprintf(ptr_names[count].name,
+					sizeof(ptr_names[count].name),
+					"tx_priority%u_%s", i,
+					rte_ixgbe_txq_strings[stat].name);
+				count++;
+				offset += RTE_ETH_XSTATS_NAME_SIZE;
+			}
+		}
+		/* FIXME: Debugging check */
+		if (cnt_stats != count)
+			return -EIO;
+	}
+	return cnt_stats;
+}
+
+static int ixgbevf_dev_xstats_names(__rte_unused struct rte_eth_dev *dev,
+	struct rte_eth_xstats_name *ptr_names, __rte_unused unsigned limit)
+{
+	unsigned i;
+
+	if (limit < IXGBEVF_NB_XSTATS)
+		return -ENOMEM;
+
+	if (ptr_names != NULL)
+		for (i = 0; i < IXGBEVF_NB_XSTATS; i++)
+			snprintf(ptr_names[i].name,
+				sizeof(ptr_names[i].name),
+				"%s", rte_ixgbevf_stats_strings[i].name);
+	return IXGBEVF_NB_XSTATS;
+}
+
 static int
 ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 					 unsigned n)
@@ -2731,8 +2807,6 @@ ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 	/* Extended stats from ixgbe_hw_stats */
 	count = 0;
 	for (i = 0; i < IXGBE_NB_HW_STATS; i++) {
-		snprintf(xstats[count].name, sizeof(xstats[count].name), "%s",
-			 rte_ixgbe_stats_strings[i].name);
 		xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
 				rte_ixgbe_stats_strings[i].offset);
 		count++;
@@ -2741,9 +2815,6 @@ ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 	/* RX Priority Stats */
 	for (stat = 0; stat < IXGBE_NB_RXQ_PRIO_STATS; stat++) {
 		for (i = 0; i < 8; i++) {
-			snprintf(xstats[count].name, sizeof(xstats[count].name),
-				 "rx_priority%u_%s", i,
-				 rte_ixgbe_rxq_strings[stat].name);
 			xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
 					rte_ixgbe_rxq_strings[stat].offset +
 					(sizeof(uint64_t) * i));
@@ -2754,16 +2825,14 @@ ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 	/* TX Priority Stats */
 	for (stat = 0; stat < IXGBE_NB_TXQ_PRIO_STATS; stat++) {
 		for (i = 0; i < 8; i++) {
-			snprintf(xstats[count].name, sizeof(xstats[count].name),
-				 "tx_priority%u_%s", i,
-				 rte_ixgbe_txq_strings[stat].name);
 			xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
 					rte_ixgbe_txq_strings[stat].offset +
 					(sizeof(uint64_t) * i));
 			count++;
 		}
 	}
-
+	for (i = 0; i < count; i++)
+		xstats[i].key = i;
 	return count;
 }
 
-- 
2.5.5

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

* [RFC PATCH v1 3/3] examples/ethtool: add xstats display command
  2016-04-15 14:44 [RFC PATCH v1 0/3] Remove string operations from xstats Remy Horton
  2016-04-15 14:44 ` [RFC PATCH v1 1/3] rte: change xstats to use integer keys Remy Horton
  2016-04-15 14:44 ` [RFC PATCH v1 2/3] drivers/net/ixgbe: change xstats to use integers Remy Horton
@ 2016-04-15 14:44 ` Remy Horton
  2016-04-20 16:03 ` [RFC PATCH v1 0/3] Remove string operations from xstats David Harton (dharton)
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 71+ messages in thread
From: Remy Horton @ 2016-04-15 14:44 UTC (permalink / raw)
  To: dev

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 examples/ethtool/ethtool-app/ethapp.c | 57 +++++++++++++++++++++++++++++++++++
 1 file changed, 57 insertions(+)

diff --git a/examples/ethtool/ethtool-app/ethapp.c b/examples/ethtool/ethtool-app/ethapp.c
index 2ed4796..16ae4e9 100644
--- a/examples/ethtool/ethtool-app/ethapp.c
+++ b/examples/ethtool/ethtool-app/ethapp.c
@@ -98,6 +98,8 @@ cmdline_parse_token_string_t pcmd_rxmode_token_cmd =
 	TOKEN_STRING_INITIALIZER(struct pcmd_int_params, cmd, "rxmode");
 cmdline_parse_token_string_t pcmd_portstats_token_cmd =
 	TOKEN_STRING_INITIALIZER(struct pcmd_int_params, cmd, "portstats");
+cmdline_parse_token_string_t pcmd_xstats_token_cmd =
+	TOKEN_STRING_INITIALIZER(struct pcmd_int_params, cmd, "xstats");
 cmdline_parse_token_num_t pcmd_int_token_port =
 	TOKEN_NUM_INITIALIZER(struct pcmd_int_params, port, UINT16);
 
@@ -552,6 +554,49 @@ static void pcmd_portstats_callback(__rte_unused void *ptr_params,
 		printf("Port %i: Error fetching statistics\n", params->port);
 }
 
+static void pcmd_xstats_callback(__rte_unused void *ptr_params,
+	__rte_unused struct cmdline *ctx,
+	__rte_unused void *ptr_data)
+{
+	struct rte_eth_xstats xstats[256];
+	struct pcmd_int_params *params = ptr_params;
+	int cnt_xstats, idx_xstat;
+	struct rte_eth_xstats_name *ptr_names;
+
+
+	if (!rte_eth_dev_is_valid_port(params->port)) {
+		printf("Error: Invalid port number %i\n", params->port);
+		return;
+	}
+
+	cnt_xstats = rte_eth_xstats_names(params->port, NULL, 0);
+	if (cnt_xstats  < 0) {
+		printf("Port %i: %s\n", params->port, strerror(-cnt_xstats));
+		return;
+	}
+	printf("Number of xstats: %i\n", cnt_xstats);
+	ptr_names = malloc(sizeof(struct rte_eth_xstats_name) * cnt_xstats);
+	if (cnt_xstats != rte_eth_xstats_names(
+			params->port, ptr_names, cnt_xstats)) {
+		printf("Error: Fetched and expected counts mismatch\n");
+		return;
+	}
+
+	cnt_xstats = rte_eth_xstats_get(params->port, xstats, 256);
+	if (cnt_xstats < 0) {
+		printf("Error: Unable to get xstats (%s)\n",
+			strerror(-cnt_xstats));
+		return;
+	}
+	for (idx_xstat = 0; idx_xstat < cnt_xstats; idx_xstat++) {
+		/* Assume ptr_names[x].id = x */
+		printf("%s: %lu\n", ptr_names[xstats[idx_xstat].key].name,
+			xstats[idx_xstat].value);
+	}
+	free(ptr_names);
+}
+
+
 static void pcmd_ringparam_callback(__rte_unused void *ptr_params,
 	__rte_unused struct cmdline *ctx,
 	void *ptr_data)
@@ -790,6 +835,17 @@ cmdline_parse_inst_t pcmd_portstats = {
 		NULL
 	},
 };
+cmdline_parse_inst_t pcmd_xstats = {
+	.f = pcmd_xstats_callback,
+	.data = NULL,
+	.help_str = "xstats <port_id>\n"
+		"     Print port eth xstats",
+	.tokens = {
+		(void *)&pcmd_xstats_token_cmd,
+		(void *)&pcmd_int_token_port,
+		NULL
+	},
+};
 cmdline_parse_inst_t pcmd_ringparam = {
 	.f = pcmd_ringparam_callback,
 	.data = NULL,
@@ -858,6 +914,7 @@ cmdline_parse_ctx_t list_prompt_commands[] = {
 	(cmdline_parse_inst_t *)&pcmd_stop,
 	(cmdline_parse_inst_t *)&pcmd_validate,
 	(cmdline_parse_inst_t *)&pcmd_vlan,
+	(cmdline_parse_inst_t *)&pcmd_xstats,
 	(cmdline_parse_inst_t *)&pcmd_quit,
 	NULL
 };
-- 
2.5.5

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

* Re: [RFC PATCH v1 0/3] Remove string operations from xstats
  2016-04-15 14:44 [RFC PATCH v1 0/3] Remove string operations from xstats Remy Horton
                   ` (2 preceding siblings ...)
  2016-04-15 14:44 ` [RFC PATCH v1 3/3] examples/ethtool: add xstats display command Remy Horton
@ 2016-04-20 16:03 ` David Harton (dharton)
  2016-04-20 16:49   ` Mcnamara, John
  2016-04-28 14:56   ` Tahhan, Maryam
  2016-04-29 12:52 ` David Harton (dharton)
  2016-05-06 11:11 ` [RFC PATCH v2 " Remy Horton
  5 siblings, 2 replies; 71+ messages in thread
From: David Harton (dharton) @ 2016-04-20 16:03 UTC (permalink / raw)
  To: Remy Horton, dev

> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Remy Horton
> Sent: Friday, April 15, 2016 10:44 AM
> To: dev@dpdk.org
> Subject: [dpdk-dev] [RFC PATCH v1 0/3] Remove string operations from
> xstats
> 
> The current extended ethernet statistics fetching involve doing several
> string operations, which causes performance issues if there are lots of
> statistics and/or network interfaces. This RFC patchset changes the API
> for xstats to use integer identifiers instead of strings and implements
> this new API for the ixgbe driver. Others drivers to follow.
> 
> --
> 
> Since this will involve API & ABI breakage as previously advertised, there
> are several design assumptions that need consideration:
> 
> *) id-name & id-value pairs for both lookup and query Permits out-of-order
> and non-contigious returning of names/ids/values, even though expected
> implmentations would in practice return items in sorted order by id. Is
> this sufficent/desirable future proofing? Idea is to allow possibility of
> drivers returning partial statistics.

I believe forcing drivers to match to a common id-space will become 
burdensome.  If the stats id-space isn't common then matching strings is 
probably just as sufficient as long as drivers don't add/remove stats
ad hoc between the time the device is initialized and removed.

> 
> *) Bulk name-id mapping lookup only
> At the moment individual lookup is not supported, as this would impose
> extra overheads on drivers. The assumption is that any end user would
> fetch all this data once on startup and then cache the mappings.

I'm not sure I see the value of looking up a single stat from a user
perspective.  I can see where the drivers might say that some stats
are less disruptive/etc but the user doesn't have that knowledge and
wouldn't know how to take advantage.  Usually all stats are grabbed
multiple times and the changes noted during debug sessions.

> 
> *) Replacement or additional API
> This patch replaces the current xstats API, but there is no inherant
> reason beyond maintainability why this funtionality could not be in
> addition rather than a replacement. What is consensus on this?

I came to the conclusion that replacing the existing API isn't necessary
but rather extending it so backwards compatibility could be maintained
during the previous discussions on this topic.  However, if we want to 
go forward with cleaning up in order to reduce the support drivers
provide I'm all for it.

I still believe the API we develop should follow an "ethtool stats like"
format as suggested earlier this year:

extern int rte_eth_xstats_names_get(uint8_t port_id,
        struct rte_eth_xstats_name *names, unsigned n);
extern int rte_eth_xstats_values_get(uint8_t port_id,
        uint64_t *values, unsigned n);

Again, these could be provided alongside the existing API or replace it.

I also like the idea you provided of a separate API to obtain the
xstats count rather than deriving the count by calling one of the
above functions with "dummy" values.

Again, I can provide the patches for the changes I've made that align
with this proposed API.  I just never got any feedback on it when
requested previously.

Regards,
Dave

> 
> Comments welcome.
> 
> Remy Horton (3):
>   rte: change xstats to use integer keys
>   drivers/net/ixgbe: change xstats to use integer keys
>   examples/ethtool: add xstats display command
> 
>  drivers/net/ixgbe/ixgbe_ethdev.c      | 87
> +++++++++++++++++++++++++++++++----
>  examples/ethtool/ethtool-app/ethapp.c | 57 +++++++++++++++++++++++
>  lib/librte_ether/rte_ethdev.c         | 87
> +++++++++++++++++++++++++++++++----
>  lib/librte_ether/rte_ethdev.h         | 38 +++++++++++++++
>  4 files changed, 252 insertions(+), 17 deletions(-)
> 
> --
> 2.5.5

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

* Re: [RFC PATCH v1 0/3] Remove string operations from xstats
  2016-04-20 16:03 ` [RFC PATCH v1 0/3] Remove string operations from xstats David Harton (dharton)
@ 2016-04-20 16:49   ` Mcnamara, John
  2016-04-22 15:04     ` David Harton (dharton)
  2016-04-28 14:56   ` Tahhan, Maryam
  1 sibling, 1 reply; 71+ messages in thread
From: Mcnamara, John @ 2016-04-20 16:49 UTC (permalink / raw)
  To: David Harton (dharton), Horton, Remy, dev; +Cc: Van Haaren, Harry

> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of David Harton
> (dharton)
> Sent: Wednesday, April 20, 2016 5:04 PM
> To: Horton, Remy <remy.horton@intel.com>; dev@dpdk.org
> Subject: Re: [dpdk-dev] [RFC PATCH v1 0/3] Remove string operations from
> xstats
> 
> 
> Again, I can provide the patches for the changes I've made that align with
> this proposed API.  I just never got any feedback on it when requested
> previously.

Hi David,

Perhaps it would be good to submit your patches, also with an RFC tag, so we can make a comparison.

Thanks,

John.
-- 

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

* Re: [RFC PATCH v1 0/3] Remove string operations from xstats
  2016-04-20 16:49   ` Mcnamara, John
@ 2016-04-22 15:04     ` David Harton (dharton)
  0 siblings, 0 replies; 71+ messages in thread
From: David Harton (dharton) @ 2016-04-22 15:04 UTC (permalink / raw)
  To: Mcnamara, John, Horton, Remy, dev; +Cc: Van Haaren, Harry



> -----Original Message-----
> From: Mcnamara, John [mailto:john.mcnamara@intel.com]
> Sent: Wednesday, April 20, 2016 12:50 PM
> To: David Harton (dharton) <dharton@cisco.com>; Horton, Remy
> <remy.horton@intel.com>; dev@dpdk.org
> Cc: Van Haaren, Harry <harry.van.haaren@intel.com>
> Subject: RE: [dpdk-dev] [RFC PATCH v1 0/3] Remove string operations from
> xstats
> 
> > -----Original Message-----
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of David Harton
> > (dharton)
> > Sent: Wednesday, April 20, 2016 5:04 PM
> > To: Horton, Remy <remy.horton@intel.com>; dev@dpdk.org
> > Subject: Re: [dpdk-dev] [RFC PATCH v1 0/3] Remove string operations
> > from xstats
> >
> >
> > Again, I can provide the patches for the changes I've made that align
> > with this proposed API.  I just never got any feedback on it when
> > requested previously.
> 
> Hi David,
> 
> Perhaps it would be good to submit your patches, also with an RFC tag, so
> we can make a comparison.

Will do.  Timing is a little bad right now due to personal commitments.

Can we wait a couple weeks?

Thanks,
Dave

> 
> Thanks,
> 
> John.
> --

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

* Re: [RFC PATCH v1 0/3] Remove string operations from xstats
  2016-04-20 16:03 ` [RFC PATCH v1 0/3] Remove string operations from xstats David Harton (dharton)
  2016-04-20 16:49   ` Mcnamara, John
@ 2016-04-28 14:56   ` Tahhan, Maryam
  2016-04-28 15:58     ` David Harton (dharton)
  1 sibling, 1 reply; 71+ messages in thread
From: Tahhan, Maryam @ 2016-04-28 14:56 UTC (permalink / raw)
  To: David Harton (dharton), Horton, Remy, dev
  Cc: Mcnamara, John, Van Haaren, Harry

> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of David Harton
> (dharton)
> Sent: Wednesday, April 20, 2016 5:04 PM
> To: Horton, Remy <remy.horton@intel.com>; dev@dpdk.org
> Subject: Re: [dpdk-dev] [RFC PATCH v1 0/3] Remove string operations
> from xstats
> 
> > -----Original Message-----
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Remy Horton
> > Sent: Friday, April 15, 2016 10:44 AM
> > To: dev@dpdk.org
> > Subject: [dpdk-dev] [RFC PATCH v1 0/3] Remove string operations from
> > xstats
> >
> > The current extended ethernet statistics fetching involve doing
> > several string operations, which causes performance issues if there
> > are lots of statistics and/or network interfaces. This RFC patchset
> > changes the API for xstats to use integer identifiers instead of
> > strings and implements this new API for the ixgbe driver. Others
> drivers to follow.
> >
> > --
> >
> > Since this will involve API & ABI breakage as previously advertised,
> > there are several design assumptions that need consideration:
> >
> > *) id-name & id-value pairs for both lookup and query Permits
> > out-of-order and non-contigious returning of names/ids/values, even
> > though expected implmentations would in practice return items in
> > sorted order by id. Is this sufficent/desirable future proofing? Idea
> > is to allow possibility of drivers returning partial statistics.
> 
> I believe forcing drivers to match to a common id-space will become
> burdensome.  If the stats id-space isn't common then matching strings is
> probably just as sufficient as long as drivers don't add/remove stats ad
> hoc between the time the device is initialized and removed.

I'm not aware of drivers adding/removing the stats ad hoc? The idea is to have a common-id space otherwise it will be a free for all and we won't have alignment across the drivers. I don't see it being any more burdensome than having a common register naming across the board which is what is there today. The advantage being that you don't have to pull the strings every time.

> 
> >
> > *) Bulk name-id mapping lookup only
> > At the moment individual lookup is not supported, as this would impose
> > extra overheads on drivers. The assumption is that any end user would
> > fetch all this data once on startup and then cache the mappings.
> 
> I'm not sure I see the value of looking up a single stat from a user
> perspective.  I can see where the drivers might say that some stats are
> less disruptive/etc but the user doesn't have that knowledge and
> wouldn't know how to take advantage.  Usually all stats are grabbed
> multiple times and the changes noted during debug sessions.
> 

I believe Remy's change doesn't suggest/support individual lookup. It is just a statement that we don't want to burden drivers with individual stats lookups.

> >
> > *) Replacement or additional API
> > This patch replaces the current xstats API, but there is no inherant
> > reason beyond maintainability why this funtionality could not be in
> > addition rather than a replacement. What is consensus on this?
> 
> I came to the conclusion that replacing the existing API isn't necessary
> but rather extending it so backwards compatibility could be maintained
> during the previous discussions on this topic.  However, if we want to go
> forward with cleaning up in order to reduce the support drivers provide
> I'm all for it.
> 
> I still believe the API we develop should follow an "ethtool stats like"
> format as suggested earlier this year:
> 
> extern int rte_eth_xstats_names_get(uint8_t port_id,
>         struct rte_eth_xstats_name *names, unsigned n); extern int
> rte_eth_xstats_values_get(uint8_t port_id,
>         uint64_t *values, unsigned n);
> 
> Again, these could be provided alongside the existing API or replace it.

I'm struggling a bit here. This is really what Remy has posted http://dpdk.org/dev/patchwork/patch/12094/ or am I missing something obvious?

> 
> I also like the idea you provided of a separate API to obtain the xstats
> count rather than deriving the count by calling one of the above
> functions with "dummy" values.

+1 

> 
> Again, I can provide the patches for the changes I've made that align
> with this proposed API.  I just never got any feedback on it when
> requested previously.

I believe time is not in our favour on this front. If you have patches can you post them, otherwise can you please review the patchset that Remy has posted?
Thanks in advance.

BR
Maryam

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

* Re: [RFC PATCH v1 0/3] Remove string operations from xstats
  2016-04-28 14:56   ` Tahhan, Maryam
@ 2016-04-28 15:58     ` David Harton (dharton)
  2016-04-29 10:21       ` Remy Horton
  0 siblings, 1 reply; 71+ messages in thread
From: David Harton (dharton) @ 2016-04-28 15:58 UTC (permalink / raw)
  To: Tahhan, Maryam, Horton, Remy, dev; +Cc: Mcnamara, John, Van Haaren, Harry

> -----Original Message-----
> From: Tahhan, Maryam [mailto:maryam.tahhan@intel.com]
> Sent: Thursday, April 28, 2016 10:56 AM
> To: David Harton (dharton) <dharton@cisco.com>; Horton, Remy
> <remy.horton@intel.com>; dev@dpdk.org
> Cc: Mcnamara, John <john.mcnamara@intel.com>; Van Haaren, Harry
> <harry.van.haaren@intel.com>
> Subject: RE: [dpdk-dev] [RFC PATCH v1 0/3] Remove string operations from
> xstats
> 
> > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of David Harton
> > (dharton)
> > Sent: Wednesday, April 20, 2016 5:04 PM
> > To: Horton, Remy <remy.horton@intel.com>; dev@dpdk.org
> > Subject: Re: [dpdk-dev] [RFC PATCH v1 0/3] Remove string operations
> > from xstats
> >
> > > -----Original Message-----
> > > From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Remy Horton
> > > Sent: Friday, April 15, 2016 10:44 AM
> > > To: dev@dpdk.org
> > > Subject: [dpdk-dev] [RFC PATCH v1 0/3] Remove string operations from
> > > xstats
> > >
> > > The current extended ethernet statistics fetching involve doing
> > > several string operations, which causes performance issues if there
> > > are lots of statistics and/or network interfaces. This RFC patchset
> > > changes the API for xstats to use integer identifiers instead of
> > > strings and implements this new API for the ixgbe driver. Others
> > drivers to follow.
> > >
> > > --
> > >
> > > Since this will involve API & ABI breakage as previously advertised,
> > > there are several design assumptions that need consideration:
> > >
> > > *) id-name & id-value pairs for both lookup and query Permits
> > > out-of-order and non-contigious returning of names/ids/values, even
> > > though expected implmentations would in practice return items in
> > > sorted order by id. Is this sufficent/desirable future proofing?
> > > Idea is to allow possibility of drivers returning partial statistics.
> >
> > I believe forcing drivers to match to a common id-space will become
> > burdensome.  If the stats id-space isn't common then matching strings
> > is probably just as sufficient as long as drivers don't add/remove
> > stats ad hoc between the time the device is initialized and removed.
> 
> I'm not aware of drivers adding/removing the stats ad hoc? The idea is to
> have a common-id space otherwise it will be a free for all and we won't
> have alignment across the drivers. I don't see it being any more
> burdensome than having a common register naming across the board which is
> what is there today. The advantage being that you don't have to pull the
> strings every time.
> 
> >
> > >
> > > *) Bulk name-id mapping lookup only
> > > At the moment individual lookup is not supported, as this would
> > > impose extra overheads on drivers. The assumption is that any end
> > > user would fetch all this data once on startup and then cache the
> mappings.
> >
> > I'm not sure I see the value of looking up a single stat from a user
> > perspective.  I can see where the drivers might say that some stats
> > are less disruptive/etc but the user doesn't have that knowledge and
> > wouldn't know how to take advantage.  Usually all stats are grabbed
> > multiple times and the changes noted during debug sessions.
> >
> 
> I believe Remy's change doesn't suggest/support individual lookup. It is
> just a statement that we don't want to burden drivers with individual
> stats lookups.
> 
> > >
> > > *) Replacement or additional API
> > > This patch replaces the current xstats API, but there is no inherant
> > > reason beyond maintainability why this funtionality could not be in
> > > addition rather than a replacement. What is consensus on this?
> >
> > I came to the conclusion that replacing the existing API isn't
> > necessary but rather extending it so backwards compatibility could be
> > maintained during the previous discussions on this topic.  However, if
> > we want to go forward with cleaning up in order to reduce the support
> > drivers provide I'm all for it.
> >
> > I still believe the API we develop should follow an "ethtool stats like"
> > format as suggested earlier this year:
> >
> > extern int rte_eth_xstats_names_get(uint8_t port_id,
> >         struct rte_eth_xstats_name *names, unsigned n); extern int
> > rte_eth_xstats_values_get(uint8_t port_id,
> >         uint64_t *values, unsigned n);
> >
> > Again, these could be provided alongside the existing API or replace it.
> 
> I'm struggling a bit here. This is really what Remy has posted
> http://dpdk.org/dev/patchwork/patch/12094/ or am I missing something
> obvious?

Maybe I misread the patch series or missed one but I don't see where 
stats can be obtained without copying strings?  This is the real issue I 
raised originally.  

Having the ability to get the names without stats is useful, but,
the real gain would be obtaining the stats without the names.

> 
> >
> > I also like the idea you provided of a separate API to obtain the
> > xstats count rather than deriving the count by calling one of the
> > above functions with "dummy" values.
> 
> +1
> 
> >
> > Again, I can provide the patches for the changes I've made that align
> > with this proposed API.  I just never got any feedback on it when
> > requested previously.
> 
> I believe time is not in our favour on this front. If you have patches can
> you post them, otherwise can you please review the patchset that Remy has
> posted?

I'm working on it but I have some process I'm navigating.  I'm hopeful 
I'll have the green light within a week if not sooner.  I apologize...
I'm pushing as hard as I can.  If you need to proceed go ahead I 
completely understand.  

All I can say is that I have implemented the API above and converted all 
drivers that supported xstats in v2.2.  Any new drivers that have added 
xstats support since would need to be added.

I did not add "get the count" because it wasn't provided in the current API
and instead followed the convention but I do believe overtly getting the
count it is the better approach.

Thanks,
Dave

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

* Re: [RFC PATCH v1 0/3] Remove string operations from xstats
  2016-04-28 15:58     ` David Harton (dharton)
@ 2016-04-29 10:21       ` Remy Horton
  2016-04-29 12:15         ` David Harton (dharton)
  0 siblings, 1 reply; 71+ messages in thread
From: Remy Horton @ 2016-04-29 10:21 UTC (permalink / raw)
  To: David Harton (dharton), Tahhan, Maryam, dev
  Cc: Mcnamara, John, Van Haaren, Harry

Morning,

On 28/04/2016 16:58, David Harton (dharton) wrote:
[..]
>>>> *) id-name & id-value pairs for both lookup and query Permits
>>>> out-of-order and non-contigious returning of names/ids/values, even
>>>> though expected implmentations would in practice return items in
>>>> sorted order by id. Is this sufficent/desirable future proofing?
>>>> Idea is to allow possibility of drivers returning partial statistics.
>>>
>>> I believe forcing drivers to match to a common id-space will become
>>> burdensome.  If the stats id-space isn't common then matching strings
>>> is probably just as sufficient as long as drivers don't add/remove
>>> stats ad hoc between the time the device is initialized and removed.
>>
>> I'm not aware of drivers adding/removing the stats ad hoc? The idea is to
>> have a common-id space otherwise it will be a free for all and we won't
>> have alignment across the drivers. I don't see it being any more
>> burdensome than having a common register naming across the board which is
>> what is there today. The advantage being that you don't have to pull the
>> strings every time.

Returning both stats (id,value) and names (id,string) as pairs would 
allow (amoung other things) common ids but actually having common ids is 
not an intended goal of mine. I think the whole idea of common ids was 
implicity vetoed when the idea of ENUMs was thrown out.

I opted for both stats and lookup to be provided as pairs because when 
it comes to APIs, I have a slight preference for having that bit of 
extra generality. Not sure its really worth it, so might change stats to 
just use id-indexed integer arrays (ethtool-like basically) rather than 
a typedef that includes the numeric id.


>>>> *) Bulk name-id mapping lookup only
[..]
>>> I'm not sure I see the value of looking up a single stat from a user
>>> perspective.  I can see where the drivers might say that some stats
>>> are less disruptive/etc but the user doesn't have that knowledge and
>>> wouldn't know how to take advantage.  Usually all stats are grabbed
>>> multiple times and the changes noted during debug sessions.
>>>
>>
>> I believe Remy's change doesn't suggest/support individual lookup. It is
>> just a statement that we don't want to burden drivers with individual
>> stats lookups.

Correct.


>>>> *) Replacement or additional API
[..]
>>> However, if
>>> we want to go forward with cleaning up in order to reduce the support
>>> drivers provide I'm all for it.

Whether we want to do such a cleanup is my open question.


> Maybe I misread the patch series or missed one but I don't see where
> stats can be obtained without copying strings?  This is the real issue I
> raised originally.

See http://dpdk.org/dev/patchwork/patch/12096/ where xstats[].key is 
used to lookup string from ptr_names[].name - I didn't delete the name 
field from rte_eth_xstats because doing so would cause a compile error 
with the drivers I've not yet converted.



> I did not add "get the count" because it wasn't provided in the current API
> and instead followed the convention but I do believe overtly getting the
> count it is the better approach.

I didn't either for the same reason, but if the API is going to be 
broken, I think it should be added.


..Remy

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

* Re: [RFC PATCH v1 0/3] Remove string operations from xstats
  2016-04-29 10:21       ` Remy Horton
@ 2016-04-29 12:15         ` David Harton (dharton)
  0 siblings, 0 replies; 71+ messages in thread
From: David Harton (dharton) @ 2016-04-29 12:15 UTC (permalink / raw)
  To: Remy Horton, Tahhan, Maryam, dev; +Cc: Mcnamara, John, Van Haaren, Harry

Happy Friday,

> -----Original Message-----
> From: Remy Horton [mailto:remy.horton@intel.com]
> Sent: Friday, April 29, 2016 6:22 AM
> To: David Harton (dharton) <dharton@cisco.com>; Tahhan, Maryam
> <maryam.tahhan@intel.com>; dev@dpdk.org
> Cc: Mcnamara, John <john.mcnamara@intel.com>; Van Haaren, Harry
> <harry.van.haaren@intel.com>
> Subject: Re: [dpdk-dev] [RFC PATCH v1 0/3] Remove string operations from
> xstats
> 
> Morning,
> 
> On 28/04/2016 16:58, David Harton (dharton) wrote:
[...]
> 
> > Maybe I misread the patch series or missed one but I don't see where
> > stats can be obtained without copying strings?  This is the real issue
> > I raised originally.
> 
> See http://dpdk.org/dev/patchwork/patch/12096/ where xstats[].key is used
> to lookup string from ptr_names[].name - I didn't delete the name field
> from rte_eth_xstats because doing so would cause a compile error with the
> drivers I've not yet converted.

Ok, this was one of my fundamental hang ups.  I didn't see any gain because
of the way the proposal is being introduced.  I guess you are saying that
not only will drivers be added in future patch series but that you also
intend to continue modifying the external API as well.

I will start a clean thread and reply/review the provided patches and forgo
my work.

Cheers,
Dave

> 
> 
> 
> > I did not add "get the count" because it wasn't provided in the
> > current API and instead followed the convention but I do believe
> > overtly getting the count it is the better approach.
> 
> I didn't either for the same reason, but if the API is going to be broken,
> I think it should be added.
> 
> 
> ..Remy

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

* Re: [RFC PATCH v1 0/3] Remove string operations from xstats
  2016-04-15 14:44 [RFC PATCH v1 0/3] Remove string operations from xstats Remy Horton
                   ` (3 preceding siblings ...)
  2016-04-20 16:03 ` [RFC PATCH v1 0/3] Remove string operations from xstats David Harton (dharton)
@ 2016-04-29 12:52 ` David Harton (dharton)
  2016-05-06 11:11 ` [RFC PATCH v2 " Remy Horton
  5 siblings, 0 replies; 71+ messages in thread
From: David Harton (dharton) @ 2016-04-29 12:52 UTC (permalink / raw)
  To: Remy Horton, dev


> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Remy Horton
> Sent: Friday, April 15, 2016 10:44 AM
> To: dev@dpdk.org
> Subject: [dpdk-dev] [RFC PATCH v1 0/3] Remove string operations from
> xstats
> 
> The current extended ethernet statistics fetching involve doing several
> string operations, which causes performance issues if there are lots of
> statistics and/or network interfaces. This RFC patchset changes the API
> for xstats to use integer identifiers instead of strings and implements
> this new API for the ixgbe driver. Others drivers to follow.
> 
> --
> 
> Since this will involve API & ABI breakage as previously advertised,
> there are several design assumptions that need consideration:
> 
> *) id-name & id-value pairs for both lookup and query
> Permits out-of-order and non-contigious returning of names/ids/values,
> even though expected implmentations would in practice return items in
> sorted order by id. Is this sufficent/desirable future proofing? Idea
> is to allow possibility of drivers returning partial statistics.

I think the key is that the order of the stats must always be honored 
and if that's the case then an id isn't necessary.  However, if others 
want an id certainly doesn't hurt.

I don't see drivers autonomously providing a subset of stats and users 
can filter out stats they don't want to their presentation layers.

> 
> *) Bulk name-id mapping lookup only
> At the moment individual lookup is not supported, as this would impose
> extra overheads on drivers. The assumption is that any end user would
> fetch all this data once on startup and then cache the mappings.

Agreed.  Similarly there is no need to return a partial list of stats 
as the presentation layers can filter.

> 
> *) Replacement or additional API
> This patch replaces the current xstats API, but there is no inherant
> reason beyond maintainability why this funtionality could not be in
> addition rather than a replacement. What is consensus on this?

I suggest 3 new functions are added:
- get number of xstats
- get xstats names
- get xstats values

This facilitates:
- parallel development within the release without breaking current usage
- possibility of removing rte_eth_xstats_get() in following release

Thanks for moving this forward,
Dave

> 
> Comments welcome.
> 
> Remy Horton (3):
>   rte: change xstats to use integer keys
>   drivers/net/ixgbe: change xstats to use integer keys
>   examples/ethtool: add xstats display command
> 
>  drivers/net/ixgbe/ixgbe_ethdev.c      | 87
> +++++++++++++++++++++++++++++++----
>  examples/ethtool/ethtool-app/ethapp.c | 57 +++++++++++++++++++++++
>  lib/librte_ether/rte_ethdev.c         | 87
> +++++++++++++++++++++++++++++++----
>  lib/librte_ether/rte_ethdev.h         | 38 +++++++++++++++
>  4 files changed, 252 insertions(+), 17 deletions(-)
> 
> --
> 2.5.5

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

* Re: [RFC PATCH v1 1/3] rte: change xstats to use integer keys
  2016-04-15 14:44 ` [RFC PATCH v1 1/3] rte: change xstats to use integer keys Remy Horton
@ 2016-04-29 13:17   ` David Harton (dharton)
  0 siblings, 0 replies; 71+ messages in thread
From: David Harton (dharton) @ 2016-04-29 13:17 UTC (permalink / raw)
  To: Remy Horton, dev, Thomas Monjalon


> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Remy Horton
> Sent: Friday, April 15, 2016 10:44 AM
> To: dev@dpdk.org; Thomas Monjalon <thomas.monjalon@6wind.com>
> Subject: [dpdk-dev] [RFC PATCH v1 1/3] rte: change xstats to use integer
> keys
> 
> Signed-off-by: Remy Horton <remy.horton@intel.com>
> ---
>  lib/librte_ether/rte_ethdev.c | 87
> +++++++++++++++++++++++++++++++++++++++----
>  lib/librte_ether/rte_ethdev.h | 38 +++++++++++++++++++
>  2 files changed, 117 insertions(+), 8 deletions(-)
> 
> diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
> index a31018e..cdd0685 100644
> --- a/lib/librte_ether/rte_ethdev.c
> +++ b/lib/librte_ether/rte_ethdev.c
> @@ -1507,6 +1507,82 @@ rte_eth_stats_reset(uint8_t port_id)
>  	dev->data->rx_mbuf_alloc_failed = 0;
>  }
> 
> +static int
> +rte_eth_xstats_count(uint8_t port_id)

Thanks for adding this.  I believe an overt API is much more clear.

> +{
> +	struct rte_eth_dev *dev;
> +	int count;
> +
> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL);
> +	dev = &rte_eth_devices[port_id];
> +	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->xstats_names, -ENOTSUP);
> +	count = (*dev->dev_ops->xstats_names)(dev, NULL, 0);
> +	if (count >= 0) {
> +		count += RTE_NB_STATS;
> +		count += dev->data->nb_rx_queues * RTE_NB_RXQ_STATS;
> +		count += dev->data->nb_tx_queues * RTE_NB_TXQ_STATS;
> +	}
> +	return count;
> +}
> +
> +int
> +rte_eth_xstats_names(uint8_t port_id, struct rte_eth_xstats_name
> *ptr_names,
> +	unsigned limit)
> +{
> +	struct rte_eth_dev *dev;
> +	int cnt_used_entries;
> +	int cnt_expected_entries;
> +	uint32_t idx, id_queue;
> +	int offset;
> +
> +	cnt_expected_entries = rte_eth_xstats_count(port_id);
> +	if (cnt_expected_entries < 0 || ptr_names == NULL)
> +		return cnt_expected_entries;

I suggest we don't provide two ways to get the number of stats and 
that users always call rte_eth_xstats_count().
Recommend returning -EINVAL if ptr_names is NULL.

> +
> +	if ((int)limit < cnt_expected_entries)
> +		return -ERANGE;
> +
> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL);
> +	dev = &rte_eth_devices[port_id];
> +	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->xstats_names, -ENOTSUP);

I think this check is too restrictive.  There are drivers that do not 
provide device specific xstats today but the xstats API will still 
return the per q stats.
Recommend skipping the device specific steps that follow.

> +	cnt_used_entries = (*dev->dev_ops->xstats_names)(
> +		dev, ptr_names, limit);
> +
> +	if (cnt_used_entries < 0)
> +		return cnt_used_entries;
> +
> +	offset = cnt_used_entries * RTE_ETH_XSTATS_NAME_SIZE;
> +	for (idx = 0; idx < RTE_NB_STATS; idx++) {
> +		snprintf(ptr_names[cnt_used_entries].name,
> +			sizeof(ptr_names[0].name),
> +			"%s", rte_stats_strings[idx].name);
> +		offset += RTE_ETH_XSTATS_NAME_SIZE;
> +		cnt_used_entries++;
> +	}
> +	for (id_queue = 0; id_queue < dev->data->nb_rx_queues; id_queue++) {
> +		for (idx = 0; idx < RTE_NB_RXQ_STATS; idx++) {
> +			snprintf(ptr_names[cnt_used_entries].name,
> +				sizeof(ptr_names[0].name),
> +				"rx_q%u%s",
> +				id_queue, rte_rxq_stats_strings[idx].name);
> +			offset += RTE_ETH_XSTATS_NAME_SIZE;
> +			cnt_used_entries++;
> +		}
> +
> +	}
> +	for (id_queue = 0; id_queue < dev->data->nb_tx_queues; id_queue++) {
> +		for (idx = 0; idx < RTE_NB_TXQ_STATS; idx++) {
> +			snprintf(ptr_names[cnt_used_entries].name,
> +				sizeof(ptr_names[0].name),
> +				"tx_q%u%s",
> +				id_queue, rte_txq_stats_strings[idx].name);
> +			offset += RTE_ETH_XSTATS_NAME_SIZE;
> +			cnt_used_entries++;
> +		}
> +	}
> +	return cnt_used_entries;
> +}
> +
>  /* retrieve ethdev extended statistics */
>  int
>  rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
> @@ -1551,8 +1627,7 @@ rte_eth_xstats_get(uint8_t port_id, struct
> rte_eth_xstats *xstats,
>  		stats_ptr = RTE_PTR_ADD(&eth_stats,
>  					rte_stats_strings[i].offset);
>  		val = *stats_ptr;
> -		snprintf(xstats[count].name, sizeof(xstats[count].name),
> -			"%s", rte_stats_strings[i].name);
> +		xstats[count].key = count + xcount;

Suggest setting adding:
xstats[count].name[0] = '\0'

until name is removed.

>  		xstats[count++].value = val;
>  	}
> 
> @@ -1563,9 +1638,7 @@ rte_eth_xstats_get(uint8_t port_id, struct
> rte_eth_xstats *xstats,
>  					rte_rxq_stats_strings[i].offset +
>  					q * sizeof(uint64_t));
>  			val = *stats_ptr;
> -			snprintf(xstats[count].name, sizeof(xstats[count].name),
> -				"rx_q%u_%s", q,
> -				rte_rxq_stats_strings[i].name);
> +			xstats[count].key = count + xcount;

Same name comment.

>  			xstats[count++].value = val;
>  		}
>  	}
> @@ -1577,9 +1650,7 @@ rte_eth_xstats_get(uint8_t port_id, struct
> rte_eth_xstats *xstats,
>  					rte_txq_stats_strings[i].offset +
>  					q * sizeof(uint64_t));
>  			val = *stats_ptr;
> -			snprintf(xstats[count].name, sizeof(xstats[count].name),
> -				"tx_q%u_%s", q,
> -				rte_txq_stats_strings[i].name);

Same name comment.

> +			xstats[count].key = count + xcount;
>  			xstats[count++].value = val;
>  		}
>  	}
> diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
> index 022733e..4b81c59 100644
> --- a/lib/librte_ether/rte_ethdev.h
> +++ b/lib/librte_ether/rte_ethdev.h
> @@ -941,10 +941,23 @@ struct rte_eth_txq_info {
>   * structure.
>   */
>  struct rte_eth_xstats {
> +	/* FIXME: Remove name[] once remaining drivers converted */
>  	char name[RTE_ETH_XSTATS_NAME_SIZE];
> +	uint64_t key;
>  	uint64_t value;
>  };
> 
> +/**
> + * A name-key lookup element for extended statistics.
> + *
> + * This structure is used to map between names and ID numbers
> + * for extended ethernet statistics.
> + */
> +struct rte_eth_xstats_name {
> +	char name[RTE_ETH_XSTATS_NAME_SIZE];
> +	uint64_t id;

Suggest naming this key as well or modifying rte_eth_xstats to use id.

> +};
> +
>  #define ETH_DCB_NUM_TCS    8
>  #define ETH_MAX_VMDQ_POOL  64
> 
> @@ -1080,6 +1093,10 @@ typedef int (*eth_xstats_get_t)(struct rte_eth_dev
> *dev,
>  typedef void (*eth_xstats_reset_t)(struct rte_eth_dev *dev);
>  /**< @internal Reset extended stats of an Ethernet device. */
> 
> +typedef int (*eth_xstats_names_t)(struct rte_eth_dev *dev,
> +	struct rte_eth_xstats_name *ptr_names, unsigned limit);
> +/**< @internal Get names of extended stats of an Ethernet device. */
> +
>  typedef int (*eth_queue_stats_mapping_set_t)(struct rte_eth_dev *dev,
>  					     uint16_t queue_id,
>  					     uint8_t stat_idx,
> @@ -1427,6 +1444,8 @@ struct eth_dev_ops {
>  	eth_stats_reset_t          stats_reset;   /**< Reset generic device
> statistics. */
>  	eth_xstats_get_t           xstats_get;    /**< Get extended device
> statistics. */
>  	eth_xstats_reset_t         xstats_reset;  /**< Reset extended device
> statistics. */
> +	eth_xstats_names_t         xstats_names;
> +	/**< Get names of extended statistics. */
>  	eth_queue_stats_mapping_set_t queue_stats_mapping_set;
>  	/**< Configure per queue stat counter mapping. */
>  	eth_dev_infos_get_t        dev_infos_get; /**< Get device info. */
> @@ -2279,6 +2298,25 @@ int rte_eth_stats_get(uint8_t port_id, struct
> rte_eth_stats *stats);
>  void rte_eth_stats_reset(uint8_t port_id);
> 
>  /**
> + * Retrieve names of extended statistics of an Ethernet device.
> + *
> + * Names within ptr_strings will be aligned to RTE_ETH_XSTATS_NAME_SIZE
> and
> + * will be listed in ascending mapping order.
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param ptr_names
> + *  Block of memory to insert names into. Must be at least limit in size.
> + *  If NULL, function returns how many statistics are available.
> + * @param limit
> + *  Capacity of ptr_strings (number of names). Ignored if ptr_string is
> NULL.
> + * @return
> + *  If successful, number of statistics; negative on error.
> + */
> +int rte_eth_xstats_names(uint8_t port_id, struct rte_eth_xstats_name
> *ptr_names,
> +	unsigned limit);
> +
> +/**
>   * Retrieve extended statistics of an Ethernet device.
>   *
>   * @param port_id
> --
> 2.5.5

Nice work.

Regards,
Dave

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

* Re: [RFC PATCH v1 2/3] drivers/net/ixgbe: change xstats to use integers
  2016-04-15 14:44 ` [RFC PATCH v1 2/3] drivers/net/ixgbe: change xstats to use integers Remy Horton
@ 2016-04-29 13:43   ` David Harton (dharton)
  2016-05-03 12:22     ` Remy Horton
  0 siblings, 1 reply; 71+ messages in thread
From: David Harton (dharton) @ 2016-04-29 13:43 UTC (permalink / raw)
  To: Remy Horton, dev, Helin Zhang


> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Remy Horton
> Sent: Friday, April 15, 2016 10:44 AM
> To: dev@dpdk.org; Helin Zhang <helin.zhang@intel.com>
> Subject: [dpdk-dev] [RFC PATCH v1 2/3] drivers/net/ixgbe: change xstats to
> use integers
> 
> Signed-off-by: Remy Horton <remy.horton@intel.com>
> ---
>  drivers/net/ixgbe/ixgbe_ethdev.c | 87
> +++++++++++++++++++++++++++++++++++-----
>  1 file changed, 78 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c
> b/drivers/net/ixgbe/ixgbe_ethdev.c
> index 3f1ebc1..4d31fe9 100644
> --- a/drivers/net/ixgbe/ixgbe_ethdev.c
> +++ b/drivers/net/ixgbe/ixgbe_ethdev.c
> @@ -179,6 +179,10 @@ static int ixgbevf_dev_xstats_get(struct rte_eth_dev
> *dev,
>  				  struct rte_eth_xstats *xstats, unsigned n);
>  static void ixgbe_dev_stats_reset(struct rte_eth_dev *dev);
>  static void ixgbe_dev_xstats_reset(struct rte_eth_dev *dev);
> +static int ixgbe_dev_xstats_names(__rte_unused struct rte_eth_dev *dev,
> +	struct rte_eth_xstats_name *ptr_names, __rte_unused unsigned limit);
> +static int ixgbevf_dev_xstats_names(__rte_unused struct rte_eth_dev *dev,
> +	struct rte_eth_xstats_name *ptr_names, __rte_unused unsigned limit);
>  static int ixgbe_dev_queue_stats_mapping_set(struct rte_eth_dev *eth_dev,
>  					     uint16_t queue_id,
>  					     uint8_t stat_idx,
> @@ -466,6 +470,7 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = {
>  	.xstats_get           = ixgbe_dev_xstats_get,
>  	.stats_reset          = ixgbe_dev_stats_reset,
>  	.xstats_reset         = ixgbe_dev_xstats_reset,
> +	.xstats_names         = ixgbe_dev_xstats_names,
>  	.queue_stats_mapping_set = ixgbe_dev_queue_stats_mapping_set,
>  	.dev_infos_get        = ixgbe_dev_info_get,
>  	.dev_supported_ptypes_get = ixgbe_dev_supported_ptypes_get,
> @@ -555,6 +560,7 @@ static const struct eth_dev_ops ixgbevf_eth_dev_ops =
> {
>  	.xstats_get           = ixgbevf_dev_xstats_get,
>  	.stats_reset          = ixgbevf_dev_stats_reset,
>  	.xstats_reset         = ixgbevf_dev_stats_reset,
> +	.xstats_names         = ixgbevf_dev_xstats_names,
>  	.dev_close            = ixgbevf_dev_close,
>  	.allmulticast_enable  = ixgbevf_dev_allmulticast_enable,
>  	.allmulticast_disable = ixgbevf_dev_allmulticast_disable,
> @@ -2698,6 +2704,76 @@ ixgbe_xstats_calc_num(void) {
>  		(IXGBE_NB_TXQ_PRIO_STATS * 8);
>  }
> 
> +static int ixgbe_dev_xstats_names(__rte_unused struct rte_eth_dev *dev,
> +	struct rte_eth_xstats_name *ptr_names, __rte_unused unsigned limit)
> +{
> +	const unsigned cnt_stats = ixgbe_xstats_calc_num();
> +	unsigned stat, i, count, offset;
> +
> +	if (ptr_names != NULL) {
> +		count = 0;
> +		offset = 0;
> +
> +		/* Note: limit >= cnt_stats checked upstream
> +		 * in rte_eth_xstats_names()
> +		 */
> +
> +		/* Extended stats from ixgbe_hw_stats */
> +		for (i = 0; i < IXGBE_NB_HW_STATS; i++) {
> +			snprintf(ptr_names[count].name,
> +				sizeof(ptr_names[count].name),
> +				"%s",
> +				rte_ixgbe_stats_strings[i].name);
> +			count++;
> +			offset += RTE_ETH_XSTATS_NAME_SIZE;
> +		}
> +
> +		/* RX Priority Stats */
> +		for (stat = 0; stat < IXGBE_NB_RXQ_PRIO_STATS; stat++) {
> +			for (i = 0; i < 8; i++) {

8 seems magical.  Is there a constant somewhere that can be used?

> +				snprintf(ptr_names[count].name,
> +					sizeof(ptr_names[count].name),
> +					"rx_priority%u_%s", i,
> +					rte_ixgbe_rxq_strings[stat].name);
> +				count++;
> +				offset += RTE_ETH_XSTATS_NAME_SIZE;
> +			}
> +		}
> +
> +		/* TX Priority Stats */
> +		for (stat = 0; stat < IXGBE_NB_TXQ_PRIO_STATS; stat++) {
> +			for (i = 0; i < 8; i++) {

Same magic number.

> +				snprintf(ptr_names[count].name,
> +					sizeof(ptr_names[count].name),
> +					"tx_priority%u_%s", i,
> +					rte_ixgbe_txq_strings[stat].name);
> +				count++;
> +				offset += RTE_ETH_XSTATS_NAME_SIZE;
> +			}
> +		}
> +		/* FIXME: Debugging check */

Just a reminder to cleanup.

> +		if (cnt_stats != count)
> +			return -EIO;
> +	}
> +	return cnt_stats;
> +}
> +
> +static int ixgbevf_dev_xstats_names(__rte_unused struct rte_eth_dev *dev,
> +	struct rte_eth_xstats_name *ptr_names, __rte_unused unsigned limit)
> +{
> +	unsigned i;
> +
> +	if (limit < IXGBEVF_NB_XSTATS)

Think this check has to be removed since rte_eth_xstats_count() calls with 
limit == 0.

> +		return -ENOMEM;
> +
> +	if (ptr_names != NULL)
> +		for (i = 0; i < IXGBEVF_NB_XSTATS; i++)
> +			snprintf(ptr_names[i].name,
> +				sizeof(ptr_names[i].name),
> +				"%s", rte_ixgbevf_stats_strings[i].name);
> +	return IXGBEVF_NB_XSTATS;
> +}
> +
>  static int
>  ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats
> *xstats,
>  					 unsigned n)
> @@ -2731,8 +2807,6 @@ ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct
> rte_eth_xstats *xstats,
>  	/* Extended stats from ixgbe_hw_stats */
>  	count = 0;
>  	for (i = 0; i < IXGBE_NB_HW_STATS; i++) {
> -		snprintf(xstats[count].name, sizeof(xstats[count].name), "%s",
> -			 rte_ixgbe_stats_strings[i].name);

Forgot to add key/id.
Also, same name comment as above.

>  		xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
>  				rte_ixgbe_stats_strings[i].offset);
>  		count++;
> @@ -2741,9 +2815,6 @@ ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct
> rte_eth_xstats *xstats,
>  	/* RX Priority Stats */
>  	for (stat = 0; stat < IXGBE_NB_RXQ_PRIO_STATS; stat++) {
>  		for (i = 0; i < 8; i++) {
> -			snprintf(xstats[count].name, sizeof(xstats[count].name),
> -				 "rx_priority%u_%s", i,
> -				 rte_ixgbe_rxq_strings[stat].name);

Add key/id...terminate name.

>  			xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
>  					rte_ixgbe_rxq_strings[stat].offset +
>  					(sizeof(uint64_t) * i));
> @@ -2754,16 +2825,14 @@ ixgbe_dev_xstats_get(struct rte_eth_dev *dev,
> struct rte_eth_xstats *xstats,
>  	/* TX Priority Stats */
>  	for (stat = 0; stat < IXGBE_NB_TXQ_PRIO_STATS; stat++) {
>  		for (i = 0; i < 8; i++) {
> -			snprintf(xstats[count].name, sizeof(xstats[count].name),
> -				 "tx_priority%u_%s", i,
> -				 rte_ixgbe_txq_strings[stat].name);

Add key/id...terminate name.

>  			xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
>  					rte_ixgbe_txq_strings[stat].offset +
>  					(sizeof(uint64_t) * i));
>  			count++;
>  		}
>  	}
> -
> +	for (i = 0; i < count; i++)
> +		xstats[i].key = i;

Suggest doing this in the loops above to be consistent with pass-thru
and likely saves some instructions.

Regards,
Dave

>  	return count;
>  }
> 
> --
> 2.5.5

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

* Re: [RFC PATCH v1 2/3] drivers/net/ixgbe: change xstats to use integers
  2016-04-29 13:43   ` David Harton (dharton)
@ 2016-05-03 12:22     ` Remy Horton
  2016-05-03 13:40       ` David Harton (dharton)
  0 siblings, 1 reply; 71+ messages in thread
From: Remy Horton @ 2016-05-03 12:22 UTC (permalink / raw)
  To: David Harton (dharton), dev, Helin Zhang


On 29/04/2016 14:43, David Harton (dharton) wrote:
[..]
>> +		/* RX Priority Stats */
>> +		for (stat = 0; stat < IXGBE_NB_RXQ_PRIO_STATS; stat++) {
>> +			for (i = 0; i < 8; i++) {
>
> 8 seems magical.  Is there a constant somewhere that can be used?

Not that I'm aware of. I've made it a #define as a small cleanup.


>> +static int ixgbevf_dev_xstats_names(__rte_unused struct rte_eth_dev *dev,
>> +	struct rte_eth_xstats_name *ptr_names, __rte_unused unsigned limit)
>> +{
>> +	unsigned i;
>> +
>> +	if (limit < IXGBEVF_NB_XSTATS)
>
> Think this check has to be removed since rte_eth_xstats_count() calls with
> limit == 0.

Well spotted. It should only error-out if ptr_names is non-NULL.

As an aside, I am wondering whether getting stats counts should itself 
be a seperate driver hook.


..Remy

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

* Re: [RFC PATCH v1 2/3] drivers/net/ixgbe: change xstats to use integers
  2016-05-03 12:22     ` Remy Horton
@ 2016-05-03 13:40       ` David Harton (dharton)
  0 siblings, 0 replies; 71+ messages in thread
From: David Harton (dharton) @ 2016-05-03 13:40 UTC (permalink / raw)
  To: Remy Horton, dev, Helin Zhang



> -----Original Message-----
> From: Remy Horton [mailto:remy.horton@intel.com]
> Sent: Tuesday, May 03, 2016 8:23 AM
> To: David Harton (dharton) <dharton@cisco.com>; dev@dpdk.org; Helin Zhang
> <helin.zhang@intel.com>
> Subject: Re: [dpdk-dev] [RFC PATCH v1 2/3] drivers/net/ixgbe: change
> xstats to use integers
> 
> 
> On 29/04/2016 14:43, David Harton (dharton) wrote:
> [..]
> >> +		/* RX Priority Stats */
> >> +		for (stat = 0; stat < IXGBE_NB_RXQ_PRIO_STATS; stat++) {
> >> +			for (i = 0; i < 8; i++) {
> >
> > 8 seems magical.  Is there a constant somewhere that can be used?
> 
> Not that I'm aware of. I've made it a #define as a small cleanup.
> 
> 
> >> +static int ixgbevf_dev_xstats_names(__rte_unused struct rte_eth_dev
> *dev,
> >> +	struct rte_eth_xstats_name *ptr_names, __rte_unused unsigned limit)
> >> +{
> >> +	unsigned i;
> >> +
> >> +	if (limit < IXGBEVF_NB_XSTATS)
> >
> > Think this check has to be removed since rte_eth_xstats_count() calls
> > with limit == 0.
> 
> Well spotted. It should only error-out if ptr_names is non-NULL.
> 
> As an aside, I am wondering whether getting stats counts should itself be
> a seperate driver hook.

I personally think it would be cleaner.  Bug, I can also see the argument of keeping
the vector table smaller and would conceded to others that felt strongly about it.

I do really like having a separate external API to the user.  A user should explicitly
ask for the count.

Cheers,
Dave

> 
> 
> ..Remy

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

* [RFC PATCH v2 0/3] Remove string operations from xstats
  2016-04-15 14:44 [RFC PATCH v1 0/3] Remove string operations from xstats Remy Horton
                   ` (4 preceding siblings ...)
  2016-04-29 12:52 ` David Harton (dharton)
@ 2016-05-06 11:11 ` Remy Horton
  2016-05-06 11:11   ` [RFC PATCH v2 1/3] rte: change xstats to use integer keys Remy Horton
                     ` (4 more replies)
  5 siblings, 5 replies; 71+ messages in thread
From: Remy Horton @ 2016-05-06 11:11 UTC (permalink / raw)
  To: dev

The current extended ethernet statistics fetching involve doing several
string operations, which causes performance issues if there are lots of
statistics and/or network interfaces. This RFC patchset changes the API
for xstats to use integer identifiers instead of strings and implements
this new API for the ixgbe driver. Others drivers to follow.

--

v2 changes:
* Fetching xstats count now seperate API function
* Added #define constants for some magic numbers
* Fixed bug with virtual function count fetching
* For non-xstats-supporting drivers, queue stats returned
* Some refactoring/cleanups
* Removed index assumption from example


Remy Horton (3):
  rte: change xstats to use integer keys
  drivers/net/ixgbe: change xstats to use integer keys
  examples/ethtool: add xstats display command

 drivers/net/ixgbe/ixgbe_ethdev.c      |  98 ++++++++++++++++++++++++++++-----
 examples/ethtool/ethtool-app/ethapp.c |  57 +++++++++++++++++++
 lib/librte_ether/rte_ethdev.c         | 100 +++++++++++++++++++++++++++++-----
 lib/librte_ether/rte_ethdev.h         |  55 +++++++++++++++++++
 4 files changed, 284 insertions(+), 26 deletions(-)

-- 
2.5.5

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

* [RFC PATCH v2 1/3] rte: change xstats to use integer keys
  2016-05-06 11:11 ` [RFC PATCH v2 " Remy Horton
@ 2016-05-06 11:11   ` Remy Horton
  2016-05-09 13:59     ` David Harton (dharton)
                       ` (2 more replies)
  2016-05-06 11:11   ` [RFC PATCH v2 2/3] drivers/net/ixgbe: change xstats to use integer id Remy Horton
                     ` (3 subsequent siblings)
  4 siblings, 3 replies; 71+ messages in thread
From: Remy Horton @ 2016-05-06 11:11 UTC (permalink / raw)
  To: dev

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 lib/librte_ether/rte_ethdev.c | 100 ++++++++++++++++++++++++++++++++++++------
 lib/librte_ether/rte_ethdev.h |  55 +++++++++++++++++++++++
 2 files changed, 142 insertions(+), 13 deletions(-)

diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index a31018e..29ba12c 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -112,7 +112,6 @@ static const struct rte_eth_xstats_name_off rte_txq_stats_strings[] = {
 #define RTE_NB_TXQ_STATS (sizeof(rte_txq_stats_strings) /	\
 		sizeof(rte_txq_stats_strings[0]))
 
-
 /**
  * The user application callback description.
  *
@@ -1507,6 +1506,87 @@ rte_eth_stats_reset(uint8_t port_id)
 	dev->data->rx_mbuf_alloc_failed = 0;
 }
 
+int
+rte_eth_xstats_count(uint8_t port_id)
+{
+	struct rte_eth_dev *dev;
+	int count;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL);
+	dev = &rte_eth_devices[port_id];
+	if (dev->dev_ops->xstats_names != NULL) {
+		count = (*dev->dev_ops->xstats_names)(dev, NULL, 0);
+		if (count < 0)
+			return count;
+	} else
+		count = 0;
+	count += RTE_NB_STATS;
+	count += dev->data->nb_rx_queues * RTE_NB_RXQ_STATS;
+	count += dev->data->nb_tx_queues * RTE_NB_TXQ_STATS;
+	return count;
+}
+
+int
+rte_eth_xstats_names(uint8_t port_id, struct rte_eth_xstats_name *ptr_names,
+	unsigned limit)
+{
+	struct rte_eth_dev *dev;
+	int cnt_used_entries;
+	int cnt_expected_entries;
+	uint32_t idx, id_queue;
+
+	if (ptr_names == NULL)
+		return -EINVAL;
+	cnt_expected_entries = rte_eth_xstats_count(port_id);
+	if (cnt_expected_entries < 0)
+		return cnt_expected_entries;
+	if ((int)limit < cnt_expected_entries)
+		return -ERANGE;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL);
+	dev = &rte_eth_devices[port_id];
+	if (dev->dev_ops->xstats_names != NULL) {
+		cnt_used_entries = (*dev->dev_ops->xstats_names)(
+			dev, ptr_names, limit);
+		if (cnt_used_entries < 0)
+			return cnt_used_entries;
+	} else
+		/* Driver itself does not support extended stats, but
+		 * still have basic stats.
+		 */
+		cnt_used_entries = 0;
+
+	for (idx = 0; idx < RTE_NB_STATS; idx++) {
+		ptr_names[cnt_used_entries].id = cnt_used_entries;
+		snprintf(ptr_names[cnt_used_entries].name,
+			sizeof(ptr_names[0].name),
+			"%s", rte_stats_strings[idx].name);
+		cnt_used_entries++;
+	}
+	for (id_queue = 0; id_queue < dev->data->nb_rx_queues; id_queue++) {
+		for (idx = 0; idx < RTE_NB_RXQ_STATS; idx++) {
+			ptr_names[cnt_used_entries].id = cnt_used_entries;
+			snprintf(ptr_names[cnt_used_entries].name,
+				sizeof(ptr_names[0].name),
+				"rx_q%u%s",
+				id_queue, rte_rxq_stats_strings[idx].name);
+			cnt_used_entries++;
+		}
+
+	}
+	for (id_queue = 0; id_queue < dev->data->nb_tx_queues; id_queue++) {
+		for (idx = 0; idx < RTE_NB_TXQ_STATS; idx++) {
+			ptr_names[cnt_used_entries].id = cnt_used_entries;
+			snprintf(ptr_names[cnt_used_entries].name,
+				sizeof(ptr_names[0].name),
+				"tx_q%u%s",
+				id_queue, rte_txq_stats_strings[idx].name);
+			cnt_used_entries++;
+		}
+	}
+	return cnt_used_entries;
+}
+
 /* retrieve ethdev extended statistics */
 int
 rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
@@ -1551,8 +1631,8 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
 		stats_ptr = RTE_PTR_ADD(&eth_stats,
 					rte_stats_strings[i].offset);
 		val = *stats_ptr;
-		snprintf(xstats[count].name, sizeof(xstats[count].name),
-			"%s", rte_stats_strings[i].name);
+		xstats[count].name[0] = '\0';
+		xstats[count].id = count + xcount;
 		xstats[count++].value = val;
 	}
 
@@ -1563,9 +1643,8 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
 					rte_rxq_stats_strings[i].offset +
 					q * sizeof(uint64_t));
 			val = *stats_ptr;
-			snprintf(xstats[count].name, sizeof(xstats[count].name),
-				"rx_q%u_%s", q,
-				rte_rxq_stats_strings[i].name);
+			xstats[count].name[0] = '\0';
+			xstats[count].id = count + xcount;
 			xstats[count++].value = val;
 		}
 	}
@@ -1577,9 +1656,8 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
 					rte_txq_stats_strings[i].offset +
 					q * sizeof(uint64_t));
 			val = *stats_ptr;
-			snprintf(xstats[count].name, sizeof(xstats[count].name),
-				"tx_q%u_%s", q,
-				rte_txq_stats_strings[i].name);
+			xstats[count].name[0] = '\0';
+			xstats[count].id = count + xcount;
 			xstats[count++].value = val;
 		}
 	}
@@ -1621,7 +1699,6 @@ set_queue_stats_mapping(uint8_t port_id, uint16_t queue_id, uint8_t stat_idx,
 			(dev, queue_id, stat_idx, is_rx);
 }
 
-
 int
 rte_eth_dev_set_tx_queue_stats_mapping(uint8_t port_id, uint16_t tx_queue_id,
 		uint8_t stat_idx)
@@ -1630,7 +1707,6 @@ rte_eth_dev_set_tx_queue_stats_mapping(uint8_t port_id, uint16_t tx_queue_id,
 			STAT_QMAP_TX);
 }
 
-
 int
 rte_eth_dev_set_rx_queue_stats_mapping(uint8_t port_id, uint16_t rx_queue_id,
 		uint8_t stat_idx)
@@ -1639,7 +1715,6 @@ rte_eth_dev_set_rx_queue_stats_mapping(uint8_t port_id, uint16_t rx_queue_id,
 			STAT_QMAP_RX);
 }
 
-
 void
 rte_eth_dev_info_get(uint8_t port_id, struct rte_eth_dev_info *dev_info)
 {
@@ -1699,7 +1774,6 @@ rte_eth_macaddr_get(uint8_t port_id, struct ether_addr *mac_addr)
 	ether_addr_copy(&dev->data->mac_addrs[0], mac_addr);
 }
 
-
 int
 rte_eth_dev_get_mtu(uint8_t port_id, uint16_t *mtu)
 {
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 022733e..eaeb703 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -941,10 +941,23 @@ struct rte_eth_txq_info {
  * structure.
  */
 struct rte_eth_xstats {
+	/* FIXME: Remove name[] once remaining drivers converted */
 	char name[RTE_ETH_XSTATS_NAME_SIZE];
+	uint64_t id;
 	uint64_t value;
 };
 
+/**
+ * A name-key lookup element for extended statistics.
+ *
+ * This structure is used to map between names and ID numbers
+ * for extended ethernet statistics.
+ */
+struct rte_eth_xstats_name {
+	char name[RTE_ETH_XSTATS_NAME_SIZE];
+	uint64_t id;
+};
+
 #define ETH_DCB_NUM_TCS    8
 #define ETH_MAX_VMDQ_POOL  64
 
@@ -1080,6 +1093,13 @@ typedef int (*eth_xstats_get_t)(struct rte_eth_dev *dev,
 typedef void (*eth_xstats_reset_t)(struct rte_eth_dev *dev);
 /**< @internal Reset extended stats of an Ethernet device. */
 
+typedef int (*eth_xstats_names_t)(struct rte_eth_dev *dev,
+	struct rte_eth_xstats_name *ptr_names, unsigned limit);
+/**< @internal Get names of extended stats of an Ethernet device. */
+
+typedef int (*eth_xstats_count_t)(struct rte_eth_dev *dev);
+/**< @internal Get count of extended stats of an Ethernet device. */
+
 typedef int (*eth_queue_stats_mapping_set_t)(struct rte_eth_dev *dev,
 					     uint16_t queue_id,
 					     uint8_t stat_idx,
@@ -1427,6 +1447,10 @@ struct eth_dev_ops {
 	eth_stats_reset_t          stats_reset;   /**< Reset generic device statistics. */
 	eth_xstats_get_t           xstats_get;    /**< Get extended device statistics. */
 	eth_xstats_reset_t         xstats_reset;  /**< Reset extended device statistics. */
+	eth_xstats_names_t         xstats_names;
+	/**< Get names of extended statistics. */
+	eth_xstats_count_t         xstats_count;
+	/**< Get number of extended statistics. */
 	eth_queue_stats_mapping_set_t queue_stats_mapping_set;
 	/**< Configure per queue stat counter mapping. */
 	eth_dev_infos_get_t        dev_infos_get; /**< Get device info. */
@@ -2279,6 +2303,37 @@ int rte_eth_stats_get(uint8_t port_id, struct rte_eth_stats *stats);
 void rte_eth_stats_reset(uint8_t port_id);
 
 /**
+ * Retrieve names of extended statistics of an Ethernet device.
+ *
+ * Names within ptr_strings will be aligned to RTE_ETH_XSTATS_NAME_SIZE and
+ * will be listed in ascending mapping order.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param ptr_names
+ *  Block of memory to insert names into. Must be at least limit in size.
+ * @param limit
+ *  Capacity of ptr_strings (number of names).
+ * @return
+ *  If successful, number of statistics; negative on error.
+ */
+int rte_eth_xstats_names(uint8_t port_id, struct rte_eth_xstats_name *ptr_names,
+	unsigned limit);
+
+/**
+ * Retrieve number of extended statistics of an Ethernet device.
+ *
+ * Names within ptr_strings will be aligned to RTE_ETH_XSTATS_NAME_SIZE and
+ * will be listed in ascending mapping order.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @return
+ *  If successful, number of statistics; negative on error.
+ */
+int rte_eth_xstats_count(uint8_t port_id);
+
+/**
  * Retrieve extended statistics of an Ethernet device.
  *
  * @param port_id
-- 
2.5.5

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

* [RFC PATCH v2 2/3] drivers/net/ixgbe: change xstats to use integer id
  2016-05-06 11:11 ` [RFC PATCH v2 " Remy Horton
  2016-05-06 11:11   ` [RFC PATCH v2 1/3] rte: change xstats to use integer keys Remy Horton
@ 2016-05-06 11:11   ` Remy Horton
  2016-05-09 14:06     ` David Harton (dharton)
  2016-05-18  8:41     ` Tahhan, Maryam
  2016-05-06 11:11   ` [RFC PATCH v2 3/3] examples/ethtool: add xstats display command Remy Horton
                     ` (2 subsequent siblings)
  4 siblings, 2 replies; 71+ messages in thread
From: Remy Horton @ 2016-05-06 11:11 UTC (permalink / raw)
  To: dev

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 drivers/net/ixgbe/ixgbe_ethdev.c | 98 ++++++++++++++++++++++++++++++++++------
 1 file changed, 85 insertions(+), 13 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 3f1ebc1..3ff8bae 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -179,6 +179,10 @@ static int ixgbevf_dev_xstats_get(struct rte_eth_dev *dev,
 				  struct rte_eth_xstats *xstats, unsigned n);
 static void ixgbe_dev_stats_reset(struct rte_eth_dev *dev);
 static void ixgbe_dev_xstats_reset(struct rte_eth_dev *dev);
+static int ixgbe_dev_xstats_names(__rte_unused struct rte_eth_dev *dev,
+	struct rte_eth_xstats_name *ptr_names, __rte_unused unsigned limit);
+static int ixgbevf_dev_xstats_names(__rte_unused struct rte_eth_dev *dev,
+	struct rte_eth_xstats_name *ptr_names, __rte_unused unsigned limit);
 static int ixgbe_dev_queue_stats_mapping_set(struct rte_eth_dev *eth_dev,
 					     uint16_t queue_id,
 					     uint8_t stat_idx,
@@ -466,6 +470,7 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = {
 	.xstats_get           = ixgbe_dev_xstats_get,
 	.stats_reset          = ixgbe_dev_stats_reset,
 	.xstats_reset         = ixgbe_dev_xstats_reset,
+	.xstats_names         = ixgbe_dev_xstats_names,
 	.queue_stats_mapping_set = ixgbe_dev_queue_stats_mapping_set,
 	.dev_infos_get        = ixgbe_dev_info_get,
 	.dev_supported_ptypes_get = ixgbe_dev_supported_ptypes_get,
@@ -555,6 +560,7 @@ static const struct eth_dev_ops ixgbevf_eth_dev_ops = {
 	.xstats_get           = ixgbevf_dev_xstats_get,
 	.stats_reset          = ixgbevf_dev_stats_reset,
 	.xstats_reset         = ixgbevf_dev_stats_reset,
+	.xstats_names         = ixgbevf_dev_xstats_names,
 	.dev_close            = ixgbevf_dev_close,
 	.allmulticast_enable  = ixgbevf_dev_allmulticast_enable,
 	.allmulticast_disable = ixgbevf_dev_allmulticast_disable,
@@ -685,6 +691,7 @@ static const struct rte_ixgbe_xstats_name_off rte_ixgbe_rxq_strings[] = {
 
 #define IXGBE_NB_RXQ_PRIO_STATS (sizeof(rte_ixgbe_rxq_strings) / \
 			   sizeof(rte_ixgbe_rxq_strings[0]))
+#define IXGBE_NB_RXQ_PRIO_VALUES 8
 
 static const struct rte_ixgbe_xstats_name_off rte_ixgbe_txq_strings[] = {
 	{"xon_packets", offsetof(struct ixgbe_hw_stats, pxontxc)},
@@ -695,6 +702,7 @@ static const struct rte_ixgbe_xstats_name_off rte_ixgbe_txq_strings[] = {
 
 #define IXGBE_NB_TXQ_PRIO_STATS (sizeof(rte_ixgbe_txq_strings) / \
 			   sizeof(rte_ixgbe_txq_strings[0]))
+#define IXGBE_NB_TXQ_PRIO_VALUES 8
 
 static const struct rte_ixgbe_xstats_name_off rte_ixgbevf_stats_strings[] = {
 	{"rx_multicast_packets", offsetof(struct ixgbevf_hw_stats, vfmprc)},
@@ -2694,8 +2702,75 @@ ixgbe_dev_stats_reset(struct rte_eth_dev *dev)
 /* This function calculates the number of xstats based on the current config */
 static unsigned
 ixgbe_xstats_calc_num(void) {
-	return IXGBE_NB_HW_STATS + (IXGBE_NB_RXQ_PRIO_STATS * 8) +
-		(IXGBE_NB_TXQ_PRIO_STATS * 8);
+	return IXGBE_NB_HW_STATS +
+		(IXGBE_NB_RXQ_PRIO_STATS * IXGBE_NB_RXQ_PRIO_VALUES) +
+		(IXGBE_NB_TXQ_PRIO_STATS * IXGBE_NB_TXQ_PRIO_VALUES);
+}
+
+static int ixgbe_dev_xstats_names(__rte_unused struct rte_eth_dev *dev,
+	struct rte_eth_xstats_name *ptr_names, __rte_unused unsigned limit)
+{
+	const unsigned cnt_stats = ixgbe_xstats_calc_num();
+	unsigned stat, i, count;
+
+	if (ptr_names != NULL) {
+		count = 0;
+
+		/* Note: limit >= cnt_stats checked upstream
+		 * in rte_eth_xstats_names()
+		 */
+
+		/* Extended stats from ixgbe_hw_stats */
+		for (i = 0; i < IXGBE_NB_HW_STATS; i++) {
+			ptr_names[count].id = count;
+			snprintf(ptr_names[count].name,
+				sizeof(ptr_names[count].name),
+				"%s",
+				rte_ixgbe_stats_strings[i].name);
+			count++;
+		}
+
+		/* RX Priority Stats */
+		for (stat = 0; stat < IXGBE_NB_RXQ_PRIO_STATS; stat++) {
+			for (i = 0; i < IXGBE_NB_RXQ_PRIO_VALUES; i++) {
+				ptr_names[count].id = count;
+				snprintf(ptr_names[count].name,
+					sizeof(ptr_names[count].name),
+					"rx_priority%u_%s", i,
+					rte_ixgbe_rxq_strings[stat].name);
+				count++;
+			}
+		}
+
+		/* TX Priority Stats */
+		for (stat = 0; stat < IXGBE_NB_TXQ_PRIO_STATS; stat++) {
+			for (i = 0; i < IXGBE_NB_TXQ_PRIO_VALUES; i++) {
+				ptr_names[count].id = count;
+				snprintf(ptr_names[count].name,
+					sizeof(ptr_names[count].name),
+					"tx_priority%u_%s", i,
+					rte_ixgbe_txq_strings[stat].name);
+				count++;
+			}
+		}
+	}
+	return cnt_stats;
+}
+
+static int ixgbevf_dev_xstats_names(__rte_unused struct rte_eth_dev *dev,
+	struct rte_eth_xstats_name *ptr_names, unsigned limit)
+{
+	unsigned i;
+
+	if (limit < IXGBEVF_NB_XSTATS && ptr_names != NULL)
+		return -ENOMEM;
+
+	if (ptr_names != NULL)
+		for (i = 0; i < IXGBEVF_NB_XSTATS; i++)
+			snprintf(ptr_names[i].name,
+				sizeof(ptr_names[i].name),
+				"%s", rte_ixgbevf_stats_strings[i].name);
+	return IXGBEVF_NB_XSTATS;
 }
 
 static int
@@ -2731,8 +2806,8 @@ ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 	/* Extended stats from ixgbe_hw_stats */
 	count = 0;
 	for (i = 0; i < IXGBE_NB_HW_STATS; i++) {
-		snprintf(xstats[count].name, sizeof(xstats[count].name), "%s",
-			 rte_ixgbe_stats_strings[i].name);
+		xstats[count].id = count;
+		xstats[count].name[0] = '\0';
 		xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
 				rte_ixgbe_stats_strings[i].offset);
 		count++;
@@ -2740,10 +2815,9 @@ ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 
 	/* RX Priority Stats */
 	for (stat = 0; stat < IXGBE_NB_RXQ_PRIO_STATS; stat++) {
-		for (i = 0; i < 8; i++) {
-			snprintf(xstats[count].name, sizeof(xstats[count].name),
-				 "rx_priority%u_%s", i,
-				 rte_ixgbe_rxq_strings[stat].name);
+		for (i = 0; i < IXGBE_NB_RXQ_PRIO_VALUES; i++) {
+			xstats[count].id = count;
+			xstats[count].name[0] = '\0';
 			xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
 					rte_ixgbe_rxq_strings[stat].offset +
 					(sizeof(uint64_t) * i));
@@ -2753,17 +2827,15 @@ ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 
 	/* TX Priority Stats */
 	for (stat = 0; stat < IXGBE_NB_TXQ_PRIO_STATS; stat++) {
-		for (i = 0; i < 8; i++) {
-			snprintf(xstats[count].name, sizeof(xstats[count].name),
-				 "tx_priority%u_%s", i,
-				 rte_ixgbe_txq_strings[stat].name);
+		for (i = 0; i < IXGBE_NB_TXQ_PRIO_VALUES; i++) {
+			xstats[count].id = count;
+			xstats[count].name[0] = '\0';
 			xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
 					rte_ixgbe_txq_strings[stat].offset +
 					(sizeof(uint64_t) * i));
 			count++;
 		}
 	}
-
 	return count;
 }
 
-- 
2.5.5

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

* [RFC PATCH v2 3/3] examples/ethtool: add xstats display command
  2016-05-06 11:11 ` [RFC PATCH v2 " Remy Horton
  2016-05-06 11:11   ` [RFC PATCH v2 1/3] rte: change xstats to use integer keys Remy Horton
  2016-05-06 11:11   ` [RFC PATCH v2 2/3] drivers/net/ixgbe: change xstats to use integer id Remy Horton
@ 2016-05-06 11:11   ` Remy Horton
  2016-05-09 14:08     ` David Harton (dharton)
  2016-05-18  8:42     ` Tahhan, Maryam
  2016-05-16 10:42   ` [RFC PATCH v2 0/3] Remove string operations from xstats Tahhan, Maryam
  2016-05-30 10:48   ` [PATCH v3 00/10] " Remy Horton
  4 siblings, 2 replies; 71+ messages in thread
From: Remy Horton @ 2016-05-06 11:11 UTC (permalink / raw)
  To: dev

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 examples/ethtool/ethtool-app/ethapp.c | 57 +++++++++++++++++++++++++++++++++++
 1 file changed, 57 insertions(+)

diff --git a/examples/ethtool/ethtool-app/ethapp.c b/examples/ethtool/ethtool-app/ethapp.c
index 2ed4796..1dc0c35 100644
--- a/examples/ethtool/ethtool-app/ethapp.c
+++ b/examples/ethtool/ethtool-app/ethapp.c
@@ -98,6 +98,8 @@ cmdline_parse_token_string_t pcmd_rxmode_token_cmd =
 	TOKEN_STRING_INITIALIZER(struct pcmd_int_params, cmd, "rxmode");
 cmdline_parse_token_string_t pcmd_portstats_token_cmd =
 	TOKEN_STRING_INITIALIZER(struct pcmd_int_params, cmd, "portstats");
+cmdline_parse_token_string_t pcmd_xstats_token_cmd =
+	TOKEN_STRING_INITIALIZER(struct pcmd_int_params, cmd, "xstats");
 cmdline_parse_token_num_t pcmd_int_token_port =
 	TOKEN_NUM_INITIALIZER(struct pcmd_int_params, port, UINT16);
 
@@ -552,6 +554,49 @@ static void pcmd_portstats_callback(__rte_unused void *ptr_params,
 		printf("Port %i: Error fetching statistics\n", params->port);
 }
 
+static void pcmd_xstats_callback(__rte_unused void *ptr_params,
+	__rte_unused struct cmdline *ctx,
+	__rte_unused void *ptr_data)
+{
+	struct rte_eth_xstats xstats[256];
+	struct pcmd_int_params *params = ptr_params;
+	int cnt_xstats, idx_xstat, idx_name;
+	struct rte_eth_xstats_name *ptr_names;
+
+	if (!rte_eth_dev_is_valid_port(params->port)) {
+		printf("Error: Invalid port number %i\n", params->port);
+		return;
+	}
+
+	cnt_xstats = rte_eth_xstats_count(params->port);
+	if (cnt_xstats  < 0) {
+		printf("Port %i: %s\n", params->port, strerror(-cnt_xstats));
+		return;
+	}
+	printf("Number of xstats: %i\n", cnt_xstats);
+	ptr_names = malloc(sizeof(struct rte_eth_xstats_name) * cnt_xstats);
+	if (cnt_xstats != rte_eth_xstats_names(
+			params->port, ptr_names, cnt_xstats)) {
+		printf("Error: Fetched and expected counts mismatch\n");
+		return;
+	}
+
+	cnt_xstats = rte_eth_xstats_get(params->port, xstats, 256);
+	if (cnt_xstats < 0) {
+		printf("Error: Unable to get xstats (%s)\n",
+			strerror(-cnt_xstats));
+		return;
+	}
+	for (idx_xstat = 0; idx_xstat < cnt_xstats; idx_xstat++)
+		for (idx_name = 0; idx_name < cnt_xstats; idx_name++)
+			if (ptr_names[idx_name].id == xstats[idx_xstat].id) {
+				printf("%s: %lu\n", ptr_names[idx_name].name,
+					xstats[idx_xstat].value);
+				break;
+			}
+	free(ptr_names);
+}
+
 static void pcmd_ringparam_callback(__rte_unused void *ptr_params,
 	__rte_unused struct cmdline *ctx,
 	void *ptr_data)
@@ -790,6 +835,17 @@ cmdline_parse_inst_t pcmd_portstats = {
 		NULL
 	},
 };
+cmdline_parse_inst_t pcmd_xstats = {
+	.f = pcmd_xstats_callback,
+	.data = NULL,
+	.help_str = "xstats <port_id>\n"
+		"     Print port eth xstats",
+	.tokens = {
+		(void *)&pcmd_xstats_token_cmd,
+		(void *)&pcmd_int_token_port,
+		NULL
+	},
+};
 cmdline_parse_inst_t pcmd_ringparam = {
 	.f = pcmd_ringparam_callback,
 	.data = NULL,
@@ -858,6 +914,7 @@ cmdline_parse_ctx_t list_prompt_commands[] = {
 	(cmdline_parse_inst_t *)&pcmd_stop,
 	(cmdline_parse_inst_t *)&pcmd_validate,
 	(cmdline_parse_inst_t *)&pcmd_vlan,
+	(cmdline_parse_inst_t *)&pcmd_xstats,
 	(cmdline_parse_inst_t *)&pcmd_quit,
 	NULL
 };
-- 
2.5.5

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

* Re: [RFC PATCH v2 1/3] rte: change xstats to use integer keys
  2016-05-06 11:11   ` [RFC PATCH v2 1/3] rte: change xstats to use integer keys Remy Horton
@ 2016-05-09 13:59     ` David Harton (dharton)
  2016-05-10  8:58       ` Remy Horton
  2016-05-12 16:17       ` Thomas Monjalon
  2016-05-16 10:47     ` Tahhan, Maryam
  2016-05-18  8:31     ` Tahhan, Maryam
  2 siblings, 2 replies; 71+ messages in thread
From: David Harton (dharton) @ 2016-05-09 13:59 UTC (permalink / raw)
  To: Remy Horton, dev


> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Remy Horton
> Sent: Friday, May 06, 2016 7:11 AM
> To: dev@dpdk.org
> Subject: [dpdk-dev] [RFC PATCH v2 1/3] rte: change xstats to use integer
> keys
> 
> Signed-off-by: Remy Horton <remy.horton@intel.com>
> ---
>  lib/librte_ether/rte_ethdev.c | 100 ++++++++++++++++++++++++++++++++++++-
> -----
>  lib/librte_ether/rte_ethdev.h |  55 +++++++++++++++++++++++
>  2 files changed, 142 insertions(+), 13 deletions(-)
> 
> diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
> index a31018e..29ba12c 100644
> --- a/lib/librte_ether/rte_ethdev.c
> +++ b/lib/librte_ether/rte_ethdev.c
> @@ -112,7 +112,6 @@ static const struct rte_eth_xstats_name_off
> rte_txq_stats_strings[] = {
>  #define RTE_NB_TXQ_STATS (sizeof(rte_txq_stats_strings) /	\
>  		sizeof(rte_txq_stats_strings[0]))
> 
> -
>  /**
>   * The user application callback description.
>   *
> @@ -1507,6 +1506,87 @@ rte_eth_stats_reset(uint8_t port_id)
>  	dev->data->rx_mbuf_alloc_failed = 0;
>  }
> 
> +int
> +rte_eth_xstats_count(uint8_t port_id)
> +{
> +	struct rte_eth_dev *dev;
> +	int count;
> +
> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL);
> +	dev = &rte_eth_devices[port_id];
> +	if (dev->dev_ops->xstats_names != NULL) {
> +		count = (*dev->dev_ops->xstats_names)(dev, NULL, 0);
> +		if (count < 0)
> +			return count;
> +	} else
> +		count = 0;
> +	count += RTE_NB_STATS;
> +	count += dev->data->nb_rx_queues * RTE_NB_RXQ_STATS;
> +	count += dev->data->nb_tx_queues * RTE_NB_TXQ_STATS;
> +	return count;
> +}
> +
> +int
> +rte_eth_xstats_names(uint8_t port_id, struct rte_eth_xstats_name
> *ptr_names,
> +	unsigned limit)
> +{
> +	struct rte_eth_dev *dev;
> +	int cnt_used_entries;
> +	int cnt_expected_entries;
> +	uint32_t idx, id_queue;
> +
> +	if (ptr_names == NULL)
> +		return -EINVAL;
> +	cnt_expected_entries = rte_eth_xstats_count(port_id);
> +	if (cnt_expected_entries < 0)
> +		return cnt_expected_entries;
> +	if ((int)limit < cnt_expected_entries)
> +		return -ERANGE;
> +
> +	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL);
> +	dev = &rte_eth_devices[port_id];
> +	if (dev->dev_ops->xstats_names != NULL) {
> +		cnt_used_entries = (*dev->dev_ops->xstats_names)(
> +			dev, ptr_names, limit);
> +		if (cnt_used_entries < 0)
> +			return cnt_used_entries;
> +	} else
> +		/* Driver itself does not support extended stats, but
> +		 * still have basic stats.
> +		 */
> +		cnt_used_entries = 0;
> +
> +	for (idx = 0; idx < RTE_NB_STATS; idx++) {
> +		ptr_names[cnt_used_entries].id = cnt_used_entries;
> +		snprintf(ptr_names[cnt_used_entries].name,
> +			sizeof(ptr_names[0].name),
> +			"%s", rte_stats_strings[idx].name);
> +		cnt_used_entries++;
> +	}
> +	for (id_queue = 0; id_queue < dev->data->nb_rx_queues; id_queue++) {
> +		for (idx = 0; idx < RTE_NB_RXQ_STATS; idx++) {
> +			ptr_names[cnt_used_entries].id = cnt_used_entries;
> +			snprintf(ptr_names[cnt_used_entries].name,
> +				sizeof(ptr_names[0].name),
> +				"rx_q%u%s",
> +				id_queue, rte_rxq_stats_strings[idx].name);
> +			cnt_used_entries++;
> +		}
> +
> +	}
> +	for (id_queue = 0; id_queue < dev->data->nb_tx_queues; id_queue++) {
> +		for (idx = 0; idx < RTE_NB_TXQ_STATS; idx++) {
> +			ptr_names[cnt_used_entries].id = cnt_used_entries;
> +			snprintf(ptr_names[cnt_used_entries].name,
> +				sizeof(ptr_names[0].name),
> +				"tx_q%u%s",
> +				id_queue, rte_txq_stats_strings[idx].name);
> +			cnt_used_entries++;
> +		}
> +	}
> +	return cnt_used_entries;
> +}
> +
>  /* retrieve ethdev extended statistics */  int
> rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats, @@ -
> 1551,8 +1631,8 @@ rte_eth_xstats_get(uint8_t port_id, struct
> rte_eth_xstats *xstats,
>  		stats_ptr = RTE_PTR_ADD(&eth_stats,
>  					rte_stats_strings[i].offset);
>  		val = *stats_ptr;
> -		snprintf(xstats[count].name, sizeof(xstats[count].name),
> -			"%s", rte_stats_strings[i].name);
> +		xstats[count].name[0] = '\0';
> +		xstats[count].id = count + xcount;
>  		xstats[count++].value = val;
>  	}
> 
> @@ -1563,9 +1643,8 @@ rte_eth_xstats_get(uint8_t port_id, struct
> rte_eth_xstats *xstats,
>  					rte_rxq_stats_strings[i].offset +
>  					q * sizeof(uint64_t));
>  			val = *stats_ptr;
> -			snprintf(xstats[count].name, sizeof(xstats[count].name),
> -				"rx_q%u_%s", q,
> -				rte_rxq_stats_strings[i].name);
> +			xstats[count].name[0] = '\0';
> +			xstats[count].id = count + xcount;
>  			xstats[count++].value = val;
>  		}
>  	}
> @@ -1577,9 +1656,8 @@ rte_eth_xstats_get(uint8_t port_id, struct
> rte_eth_xstats *xstats,
>  					rte_txq_stats_strings[i].offset +
>  					q * sizeof(uint64_t));
>  			val = *stats_ptr;
> -			snprintf(xstats[count].name, sizeof(xstats[count].name),
> -				"tx_q%u_%s", q,
> -				rte_txq_stats_strings[i].name);
> +			xstats[count].name[0] = '\0';
> +			xstats[count].id = count + xcount;
>  			xstats[count++].value = val;
>  		}
>  	}
> @@ -1621,7 +1699,6 @@ set_queue_stats_mapping(uint8_t port_id, uint16_t
> queue_id, uint8_t stat_idx,
>  			(dev, queue_id, stat_idx, is_rx);
>  }
> 
> -

Not sure how the community feels about white-space only changes.
Just mentioning in case some folks get excited about it.  One here and a few below.

>  int
>  rte_eth_dev_set_tx_queue_stats_mapping(uint8_t port_id, uint16_t
> tx_queue_id,
>  		uint8_t stat_idx)
> @@ -1630,7 +1707,6 @@ rte_eth_dev_set_tx_queue_stats_mapping(uint8_t
> port_id, uint16_t tx_queue_id,
>  			STAT_QMAP_TX);
>  }
> 
> -
>  int
>  rte_eth_dev_set_rx_queue_stats_mapping(uint8_t port_id, uint16_t
> rx_queue_id,
>  		uint8_t stat_idx)
> @@ -1639,7 +1715,6 @@ rte_eth_dev_set_rx_queue_stats_mapping(uint8_t
> port_id, uint16_t rx_queue_id,
>  			STAT_QMAP_RX);
>  }
> 
> -
>  void
>  rte_eth_dev_info_get(uint8_t port_id, struct rte_eth_dev_info *dev_info)
> { @@ -1699,7 +1774,6 @@ rte_eth_macaddr_get(uint8_t port_id, struct
> ether_addr *mac_addr)
>  	ether_addr_copy(&dev->data->mac_addrs[0], mac_addr);  }
> 
> -
>  int
>  rte_eth_dev_get_mtu(uint8_t port_id, uint16_t *mtu)  { diff --git
> a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h index
> 022733e..eaeb703 100644
> --- a/lib/librte_ether/rte_ethdev.h
> +++ b/lib/librte_ether/rte_ethdev.h
> @@ -941,10 +941,23 @@ struct rte_eth_txq_info {
>   * structure.
>   */
>  struct rte_eth_xstats {
> +	/* FIXME: Remove name[] once remaining drivers converted */
>  	char name[RTE_ETH_XSTATS_NAME_SIZE];
> +	uint64_t id;
>  	uint64_t value;
>  };
> 
> +/**
> + * A name-key lookup element for extended statistics.
> + *
> + * This structure is used to map between names and ID numbers
> + * for extended ethernet statistics.
> + */
> +struct rte_eth_xstats_name {
> +	char name[RTE_ETH_XSTATS_NAME_SIZE];
> +	uint64_t id;
> +};
> +
>  #define ETH_DCB_NUM_TCS    8
>  #define ETH_MAX_VMDQ_POOL  64
> 
> @@ -1080,6 +1093,13 @@ typedef int (*eth_xstats_get_t)(struct rte_eth_dev
> *dev,  typedef void (*eth_xstats_reset_t)(struct rte_eth_dev *dev);  /**<
> @internal Reset extended stats of an Ethernet device. */
> 
> +typedef int (*eth_xstats_names_t)(struct rte_eth_dev *dev,
> +	struct rte_eth_xstats_name *ptr_names, unsigned limit); /**<
> @internal
> +Get names of extended stats of an Ethernet device. */
> +
> +typedef int (*eth_xstats_count_t)(struct rte_eth_dev *dev); /**<
> +@internal Get count of extended stats of an Ethernet device. */
> +
>  typedef int (*eth_queue_stats_mapping_set_t)(struct rte_eth_dev *dev,
>  					     uint16_t queue_id,
>  					     uint8_t stat_idx,
> @@ -1427,6 +1447,10 @@ struct eth_dev_ops {
>  	eth_stats_reset_t          stats_reset;   /**< Reset generic device
> statistics. */
>  	eth_xstats_get_t           xstats_get;    /**< Get extended device
> statistics. */
>  	eth_xstats_reset_t         xstats_reset;  /**< Reset extended device
> statistics. */
> +	eth_xstats_names_t         xstats_names;
> +	/**< Get names of extended statistics. */
> +	eth_xstats_count_t         xstats_count;
> +	/**< Get number of extended statistics. */
>  	eth_queue_stats_mapping_set_t queue_stats_mapping_set;
>  	/**< Configure per queue stat counter mapping. */
>  	eth_dev_infos_get_t        dev_infos_get; /**< Get device info. */
> @@ -2279,6 +2303,37 @@ int rte_eth_stats_get(uint8_t port_id, struct
> rte_eth_stats *stats);  void rte_eth_stats_reset(uint8_t port_id);
> 
>  /**
> + * Retrieve names of extended statistics of an Ethernet device.
> + *
> + * Names within ptr_strings will be aligned to RTE_ETH_XSTATS_NAME_SIZE
> +and
> + * will be listed in ascending mapping order.
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param ptr_names
> + *  Block of memory to insert names into. Must be at least limit in size.
> + * @param limit
> + *  Capacity of ptr_strings (number of names).
> + * @return
> + *  If successful, number of statistics; negative on error.
> + */
> +int rte_eth_xstats_names(uint8_t port_id, struct rte_eth_xstats_name
> *ptr_names,
> +	unsigned limit);
> +
> +/**
> + * Retrieve number of extended statistics of an Ethernet device.
> + *
> + * Names within ptr_strings will be aligned to RTE_ETH_XSTATS_NAME_SIZE
> +and
> + * will be listed in ascending mapping order.
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @return
> + *  If successful, number of statistics; negative on error.
> + */
> +int rte_eth_xstats_count(uint8_t port_id);
> +
> +/**
>   * Retrieve extended statistics of an Ethernet device.
>   *
>   * @param port_id
> --
> 2.5.5

Acked-by: David Harton <dharton@cisco.com>

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

* Re: [RFC PATCH v2 2/3] drivers/net/ixgbe: change xstats to use integer id
  2016-05-06 11:11   ` [RFC PATCH v2 2/3] drivers/net/ixgbe: change xstats to use integer id Remy Horton
@ 2016-05-09 14:06     ` David Harton (dharton)
  2016-05-18  8:41     ` Tahhan, Maryam
  1 sibling, 0 replies; 71+ messages in thread
From: David Harton (dharton) @ 2016-05-09 14:06 UTC (permalink / raw)
  To: Remy Horton, dev


> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Remy Horton
> Sent: Friday, May 06, 2016 7:11 AM
> To: dev@dpdk.org
> Subject: [dpdk-dev] [RFC PATCH v2 2/3] drivers/net/ixgbe: change xstats to
> use integer id
> 
> Signed-off-by: Remy Horton <remy.horton@intel.com>
> ---
>  drivers/net/ixgbe/ixgbe_ethdev.c | 98 ++++++++++++++++++++++++++++++++++-
> -----
>  1 file changed, 85 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c
> b/drivers/net/ixgbe/ixgbe_ethdev.c
> index 3f1ebc1..3ff8bae 100644
> --- a/drivers/net/ixgbe/ixgbe_ethdev.c
> +++ b/drivers/net/ixgbe/ixgbe_ethdev.c
> @@ -179,6 +179,10 @@ static int ixgbevf_dev_xstats_get(struct rte_eth_dev
> *dev,
>  				  struct rte_eth_xstats *xstats, unsigned n);
>  static void ixgbe_dev_stats_reset(struct rte_eth_dev *dev);
>  static void ixgbe_dev_xstats_reset(struct rte_eth_dev *dev);
> +static int ixgbe_dev_xstats_names(__rte_unused struct rte_eth_dev *dev,
> +	struct rte_eth_xstats_name *ptr_names, __rte_unused unsigned limit);
> +static int ixgbevf_dev_xstats_names(__rte_unused struct rte_eth_dev *dev,
> +	struct rte_eth_xstats_name *ptr_names, __rte_unused unsigned limit);
>  static int ixgbe_dev_queue_stats_mapping_set(struct rte_eth_dev *eth_dev,
>  					     uint16_t queue_id,
>  					     uint8_t stat_idx,
> @@ -466,6 +470,7 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = {
>  	.xstats_get           = ixgbe_dev_xstats_get,
>  	.stats_reset          = ixgbe_dev_stats_reset,
>  	.xstats_reset         = ixgbe_dev_xstats_reset,
> +	.xstats_names         = ixgbe_dev_xstats_names,
>  	.queue_stats_mapping_set = ixgbe_dev_queue_stats_mapping_set,
>  	.dev_infos_get        = ixgbe_dev_info_get,
>  	.dev_supported_ptypes_get = ixgbe_dev_supported_ptypes_get,
> @@ -555,6 +560,7 @@ static const struct eth_dev_ops ixgbevf_eth_dev_ops =
> {
>  	.xstats_get           = ixgbevf_dev_xstats_get,
>  	.stats_reset          = ixgbevf_dev_stats_reset,
>  	.xstats_reset         = ixgbevf_dev_stats_reset,
> +	.xstats_names         = ixgbevf_dev_xstats_names,
>  	.dev_close            = ixgbevf_dev_close,
>  	.allmulticast_enable  = ixgbevf_dev_allmulticast_enable,
>  	.allmulticast_disable = ixgbevf_dev_allmulticast_disable,
> @@ -685,6 +691,7 @@ static const struct rte_ixgbe_xstats_name_off
> rte_ixgbe_rxq_strings[] = {
> 
>  #define IXGBE_NB_RXQ_PRIO_STATS (sizeof(rte_ixgbe_rxq_strings) / \
>  			   sizeof(rte_ixgbe_rxq_strings[0]))
> +#define IXGBE_NB_RXQ_PRIO_VALUES 8
> 
>  static const struct rte_ixgbe_xstats_name_off rte_ixgbe_txq_strings[] = {
>  	{"xon_packets", offsetof(struct ixgbe_hw_stats, pxontxc)},
> @@ -695,6 +702,7 @@ static const struct rte_ixgbe_xstats_name_off
> rte_ixgbe_txq_strings[] = {
> 
>  #define IXGBE_NB_TXQ_PRIO_STATS (sizeof(rte_ixgbe_txq_strings) / \
>  			   sizeof(rte_ixgbe_txq_strings[0]))
> +#define IXGBE_NB_TXQ_PRIO_VALUES 8
> 
>  static const struct rte_ixgbe_xstats_name_off rte_ixgbevf_stats_strings[]
> = {
>  	{"rx_multicast_packets", offsetof(struct ixgbevf_hw_stats, vfmprc)},
> @@ -2694,8 +2702,75 @@ ixgbe_dev_stats_reset(struct rte_eth_dev *dev)
>  /* This function calculates the number of xstats based on the current
> config */
>  static unsigned
>  ixgbe_xstats_calc_num(void) {
> -	return IXGBE_NB_HW_STATS + (IXGBE_NB_RXQ_PRIO_STATS * 8) +
> -		(IXGBE_NB_TXQ_PRIO_STATS * 8);
> +	return IXGBE_NB_HW_STATS +
> +		(IXGBE_NB_RXQ_PRIO_STATS * IXGBE_NB_RXQ_PRIO_VALUES) +
> +		(IXGBE_NB_TXQ_PRIO_STATS * IXGBE_NB_TXQ_PRIO_VALUES);

Nice cleanup.

> +}
> +
> +static int ixgbe_dev_xstats_names(__rte_unused struct rte_eth_dev *dev,
> +	struct rte_eth_xstats_name *ptr_names, __rte_unused unsigned limit)
> +{
> +	const unsigned cnt_stats = ixgbe_xstats_calc_num();
> +	unsigned stat, i, count;
> +
> +	if (ptr_names != NULL) {
> +		count = 0;
> +
> +		/* Note: limit >= cnt_stats checked upstream
> +		 * in rte_eth_xstats_names()
> +		 */
> +
> +		/* Extended stats from ixgbe_hw_stats */
> +		for (i = 0; i < IXGBE_NB_HW_STATS; i++) {
> +			ptr_names[count].id = count;
> +			snprintf(ptr_names[count].name,
> +				sizeof(ptr_names[count].name),
> +				"%s",
> +				rte_ixgbe_stats_strings[i].name);
> +			count++;
> +		}
> +
> +		/* RX Priority Stats */
> +		for (stat = 0; stat < IXGBE_NB_RXQ_PRIO_STATS; stat++) {
> +			for (i = 0; i < IXGBE_NB_RXQ_PRIO_VALUES; i++) {
> +				ptr_names[count].id = count;
> +				snprintf(ptr_names[count].name,
> +					sizeof(ptr_names[count].name),
> +					"rx_priority%u_%s", i,
> +					rte_ixgbe_rxq_strings[stat].name);
> +				count++;
> +			}
> +		}
> +
> +		/* TX Priority Stats */
> +		for (stat = 0; stat < IXGBE_NB_TXQ_PRIO_STATS; stat++) {
> +			for (i = 0; i < IXGBE_NB_TXQ_PRIO_VALUES; i++) {
> +				ptr_names[count].id = count;
> +				snprintf(ptr_names[count].name,
> +					sizeof(ptr_names[count].name),
> +					"tx_priority%u_%s", i,
> +					rte_ixgbe_txq_strings[stat].name);
> +				count++;
> +			}
> +		}
> +	}
> +	return cnt_stats;
> +}
> +
> +static int ixgbevf_dev_xstats_names(__rte_unused struct rte_eth_dev *dev,
> +	struct rte_eth_xstats_name *ptr_names, unsigned limit)
> +{
> +	unsigned i;
> +
> +	if (limit < IXGBEVF_NB_XSTATS && ptr_names != NULL)
> +		return -ENOMEM;
> +
> +	if (ptr_names != NULL)
> +		for (i = 0; i < IXGBEVF_NB_XSTATS; i++)
> +			snprintf(ptr_names[i].name,
> +				sizeof(ptr_names[i].name),
> +				"%s", rte_ixgbevf_stats_strings[i].name);
> +	return IXGBEVF_NB_XSTATS;
>  }
> 
>  static int
> @@ -2731,8 +2806,8 @@ ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct
> rte_eth_xstats *xstats,
>  	/* Extended stats from ixgbe_hw_stats */
>  	count = 0;
>  	for (i = 0; i < IXGBE_NB_HW_STATS; i++) {
> -		snprintf(xstats[count].name, sizeof(xstats[count].name), "%s",
> -			 rte_ixgbe_stats_strings[i].name);
> +		xstats[count].id = count;
> +		xstats[count].name[0] = '\0';
>  		xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
>  				rte_ixgbe_stats_strings[i].offset);
>  		count++;
> @@ -2740,10 +2815,9 @@ ixgbe_dev_xstats_get(struct rte_eth_dev *dev,
> struct rte_eth_xstats *xstats,
> 
>  	/* RX Priority Stats */
>  	for (stat = 0; stat < IXGBE_NB_RXQ_PRIO_STATS; stat++) {
> -		for (i = 0; i < 8; i++) {
> -			snprintf(xstats[count].name, sizeof(xstats[count].name),
> -				 "rx_priority%u_%s", i,
> -				 rte_ixgbe_rxq_strings[stat].name);
> +		for (i = 0; i < IXGBE_NB_RXQ_PRIO_VALUES; i++) {
> +			xstats[count].id = count;
> +			xstats[count].name[0] = '\0';
>  			xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
>  					rte_ixgbe_rxq_strings[stat].offset +
>  					(sizeof(uint64_t) * i));
> @@ -2753,17 +2827,15 @@ ixgbe_dev_xstats_get(struct rte_eth_dev *dev,
> struct rte_eth_xstats *xstats,
> 
>  	/* TX Priority Stats */
>  	for (stat = 0; stat < IXGBE_NB_TXQ_PRIO_STATS; stat++) {
> -		for (i = 0; i < 8; i++) {
> -			snprintf(xstats[count].name, sizeof(xstats[count].name),
> -				 "tx_priority%u_%s", i,
> -				 rte_ixgbe_txq_strings[stat].name);
> +		for (i = 0; i < IXGBE_NB_TXQ_PRIO_VALUES; i++) {
> +			xstats[count].id = count;
> +			xstats[count].name[0] = '\0';
>  			xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
>  					rte_ixgbe_txq_strings[stat].offset +
>  					(sizeof(uint64_t) * i));
>  			count++;
>  		}
>  	}
> -
>  	return count;
>  }
> 
> --
> 2.5.5

Acked-by: David Harton <dharton@cisco.com>

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

* Re: [RFC PATCH v2 3/3] examples/ethtool: add xstats display command
  2016-05-06 11:11   ` [RFC PATCH v2 3/3] examples/ethtool: add xstats display command Remy Horton
@ 2016-05-09 14:08     ` David Harton (dharton)
  2016-05-18  8:42     ` Tahhan, Maryam
  1 sibling, 0 replies; 71+ messages in thread
From: David Harton (dharton) @ 2016-05-09 14:08 UTC (permalink / raw)
  To: Remy Horton, dev



> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Remy Horton
> Sent: Friday, May 06, 2016 7:11 AM
> To: dev@dpdk.org
> Subject: [dpdk-dev] [RFC PATCH v2 3/3] examples/ethtool: add xstats
> display command
> 
> Signed-off-by: Remy Horton <remy.horton@intel.com>
> ---
>  examples/ethtool/ethtool-app/ethapp.c | 57
> +++++++++++++++++++++++++++++++++++
>  1 file changed, 57 insertions(+)
> 
> diff --git a/examples/ethtool/ethtool-app/ethapp.c
> b/examples/ethtool/ethtool-app/ethapp.c
> index 2ed4796..1dc0c35 100644
> --- a/examples/ethtool/ethtool-app/ethapp.c
> +++ b/examples/ethtool/ethtool-app/ethapp.c
> @@ -98,6 +98,8 @@ cmdline_parse_token_string_t pcmd_rxmode_token_cmd =
>  	TOKEN_STRING_INITIALIZER(struct pcmd_int_params, cmd, "rxmode");
>  cmdline_parse_token_string_t pcmd_portstats_token_cmd =
>  	TOKEN_STRING_INITIALIZER(struct pcmd_int_params, cmd, "portstats");
> +cmdline_parse_token_string_t pcmd_xstats_token_cmd =
> +	TOKEN_STRING_INITIALIZER(struct pcmd_int_params, cmd, "xstats");
>  cmdline_parse_token_num_t pcmd_int_token_port =
>  	TOKEN_NUM_INITIALIZER(struct pcmd_int_params, port, UINT16);
> 
> @@ -552,6 +554,49 @@ static void pcmd_portstats_callback(__rte_unused void
> *ptr_params,
>  		printf("Port %i: Error fetching statistics\n", params->port);
>  }
> 
> +static void pcmd_xstats_callback(__rte_unused void *ptr_params,
> +	__rte_unused struct cmdline *ctx,
> +	__rte_unused void *ptr_data)
> +{
> +	struct rte_eth_xstats xstats[256];
> +	struct pcmd_int_params *params = ptr_params;
> +	int cnt_xstats, idx_xstat, idx_name;
> +	struct rte_eth_xstats_name *ptr_names;
> +
> +	if (!rte_eth_dev_is_valid_port(params->port)) {
> +		printf("Error: Invalid port number %i\n", params->port);
> +		return;
> +	}
> +
> +	cnt_xstats = rte_eth_xstats_count(params->port);
> +	if (cnt_xstats  < 0) {
> +		printf("Port %i: %s\n", params->port, strerror(-cnt_xstats));
> +		return;
> +	}
> +	printf("Number of xstats: %i\n", cnt_xstats);
> +	ptr_names = malloc(sizeof(struct rte_eth_xstats_name) * cnt_xstats);
> +	if (cnt_xstats != rte_eth_xstats_names(
> +			params->port, ptr_names, cnt_xstats)) {
> +		printf("Error: Fetched and expected counts mismatch\n");
> +		return;
> +	}
> +
> +	cnt_xstats = rte_eth_xstats_get(params->port, xstats, 256);
> +	if (cnt_xstats < 0) {
> +		printf("Error: Unable to get xstats (%s)\n",
> +			strerror(-cnt_xstats));
> +		return;
> +	}
> +	for (idx_xstat = 0; idx_xstat < cnt_xstats; idx_xstat++)
> +		for (idx_name = 0; idx_name < cnt_xstats; idx_name++)
> +			if (ptr_names[idx_name].id == xstats[idx_xstat].id) {
> +				printf("%s: %lu\n", ptr_names[idx_name].name,
> +					xstats[idx_xstat].value);
> +				break;
> +			}
> +	free(ptr_names);
> +}
> +
>  static void pcmd_ringparam_callback(__rte_unused void *ptr_params,
>  	__rte_unused struct cmdline *ctx,
>  	void *ptr_data)
> @@ -790,6 +835,17 @@ cmdline_parse_inst_t pcmd_portstats = {
>  		NULL
>  	},
>  };
> +cmdline_parse_inst_t pcmd_xstats = {
> +	.f = pcmd_xstats_callback,
> +	.data = NULL,
> +	.help_str = "xstats <port_id>\n"
> +		"     Print port eth xstats",
> +	.tokens = {
> +		(void *)&pcmd_xstats_token_cmd,
> +		(void *)&pcmd_int_token_port,
> +		NULL
> +	},
> +};
>  cmdline_parse_inst_t pcmd_ringparam = {
>  	.f = pcmd_ringparam_callback,
>  	.data = NULL,
> @@ -858,6 +914,7 @@ cmdline_parse_ctx_t list_prompt_commands[] = {
>  	(cmdline_parse_inst_t *)&pcmd_stop,
>  	(cmdline_parse_inst_t *)&pcmd_validate,
>  	(cmdline_parse_inst_t *)&pcmd_vlan,
> +	(cmdline_parse_inst_t *)&pcmd_xstats,
>  	(cmdline_parse_inst_t *)&pcmd_quit,
>  	NULL
>  };
> --
> 2.5.5

Acked-by: David Harton <dharton@cisco.com>

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

* Re: [RFC PATCH v2 1/3] rte: change xstats to use integer keys
  2016-05-09 13:59     ` David Harton (dharton)
@ 2016-05-10  8:58       ` Remy Horton
  2016-05-12 16:17       ` Thomas Monjalon
  1 sibling, 0 replies; 71+ messages in thread
From: Remy Horton @ 2016-05-10  8:58 UTC (permalink / raw)
  To: David Harton (dharton), dev



On 09/05/2016 14:59, David Harton (dharton) wrote:
[..]
>>   }
>>
>> -
>
> Not sure how the community feels about white-space only changes.
> Just mentioning in case some folks get excited about it.  One here and a few below.

I doubt it'll be showstopper. In any case hoping to get a v3 out that 
converts the 4 other drivers that have xstats.

..Remy

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

* Re: [RFC PATCH v2 1/3] rte: change xstats to use integer keys
  2016-05-09 13:59     ` David Harton (dharton)
  2016-05-10  8:58       ` Remy Horton
@ 2016-05-12 16:17       ` Thomas Monjalon
  1 sibling, 0 replies; 71+ messages in thread
From: Thomas Monjalon @ 2016-05-12 16:17 UTC (permalink / raw)
  To: David Harton (dharton), Remy Horton; +Cc: dev

2016-05-09 13:59, David Harton:
> >  }
> > 
> > -
> 
> Not sure how the community feels about white-space only changes.
> Just mentioning in case some folks get excited about it.  One here and a few below.

It's a trivial cleanup. No problem I think.

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

* Re: [RFC PATCH v2 0/3] Remove string operations from xstats
  2016-05-06 11:11 ` [RFC PATCH v2 " Remy Horton
                     ` (2 preceding siblings ...)
  2016-05-06 11:11   ` [RFC PATCH v2 3/3] examples/ethtool: add xstats display command Remy Horton
@ 2016-05-16 10:42   ` Tahhan, Maryam
  2016-05-18 10:12     ` Remy Horton
  2016-05-30 10:48   ` [PATCH v3 00/10] " Remy Horton
  4 siblings, 1 reply; 71+ messages in thread
From: Tahhan, Maryam @ 2016-05-16 10:42 UTC (permalink / raw)
  To: Horton, Remy, dev

> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Remy Horton
> Sent: Friday, May 6, 2016 12:11 PM
> To: dev@dpdk.org
> Subject: [dpdk-dev] [RFC PATCH v2 0/3] Remove string operations from
> xstats
> 
> The current extended ethernet statistics fetching involve doing several
> string operations, which causes performance issues if there are lots of
> statistics and/or network interfaces. This RFC patchset changes the API
> for xstats to use integer identifiers instead of strings and implements this
> new API for the ixgbe driver. Others drivers to follow.
> 
> --
> 
> v2 changes:
> * Fetching xstats count now seperate API function
> * Added #define constants for some magic numbers
> * Fixed bug with virtual function count fetching
> * For non-xstats-supporting drivers, queue stats returned
> * Some refactoring/cleanups
> * Removed index assumption from example
> 
> 
> Remy Horton (3):
>   rte: change xstats to use integer keys
>   drivers/net/ixgbe: change xstats to use integer keys
>   examples/ethtool: add xstats display command
> 
>  drivers/net/ixgbe/ixgbe_ethdev.c      |  98
> ++++++++++++++++++++++++++++-----
>  examples/ethtool/ethtool-app/ethapp.c |  57 +++++++++++++++++++
>  lib/librte_ether/rte_ethdev.c         | 100
> +++++++++++++++++++++++++++++-----
>  lib/librte_ether/rte_ethdev.h         |  55 +++++++++++++++++++
>  4 files changed, 284 insertions(+), 26 deletions(-)
> 
> --
> 2.5.5

Looks Great overall. Is there a need to update prog_guide/poll_mode_drv.rst with the new mods?

BR
Maryam

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

* Re: [RFC PATCH v2 1/3] rte: change xstats to use integer keys
  2016-05-06 11:11   ` [RFC PATCH v2 1/3] rte: change xstats to use integer keys Remy Horton
  2016-05-09 13:59     ` David Harton (dharton)
@ 2016-05-16 10:47     ` Tahhan, Maryam
  2016-05-18  8:31     ` Tahhan, Maryam
  2 siblings, 0 replies; 71+ messages in thread
From: Tahhan, Maryam @ 2016-05-16 10:47 UTC (permalink / raw)
  To: Horton, Remy, dev

> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Remy Horton
> Sent: Friday, May 6, 2016 12:11 PM
> To: dev@dpdk.org
> Subject: [dpdk-dev] [RFC PATCH v2 1/3] rte: change xstats to use integer
> keys
> 
> Signed-off-by: Remy Horton <remy.horton@intel.com>
> ---
Acked-by: Maryam Tahhan <maryam.tahhan@intel.com>

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

* Re: [RFC PATCH v2 1/3] rte: change xstats to use integer keys
  2016-05-06 11:11   ` [RFC PATCH v2 1/3] rte: change xstats to use integer keys Remy Horton
  2016-05-09 13:59     ` David Harton (dharton)
  2016-05-16 10:47     ` Tahhan, Maryam
@ 2016-05-18  8:31     ` Tahhan, Maryam
  2016-05-18  8:45       ` Remy Horton
  2 siblings, 1 reply; 71+ messages in thread
From: Tahhan, Maryam @ 2016-05-18  8:31 UTC (permalink / raw)
  To: Horton, Remy, dev

<snip>
>  					     uint8_t stat_idx,
> @@ -1427,6 +1447,10 @@ struct eth_dev_ops {
>  	eth_stats_reset_t          stats_reset;   /**< Reset generic device
> statistics. */
>  	eth_xstats_get_t           xstats_get;    /**< Get extended device
> statistics. */
>  	eth_xstats_reset_t         xstats_reset;  /**< Reset extended
> device statistics. */
> +	eth_xstats_names_t         xstats_names;
> +	/**< Get names of extended statistics. */
> +	eth_xstats_count_t         xstats_count;
> +	/**< Get number of extended statistics. */

Hi Remy
While reviewing the second patch in this patchset I noticed you aren't actually using 
eth_xstats_count_t   xstats_count in the eth_dev_ops to retrieve the count in the driver. 
Do you still need xstats_count?

BR
Maryam
<snip>

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

* Re: [RFC PATCH v2 2/3] drivers/net/ixgbe: change xstats to use integer id
  2016-05-06 11:11   ` [RFC PATCH v2 2/3] drivers/net/ixgbe: change xstats to use integer id Remy Horton
  2016-05-09 14:06     ` David Harton (dharton)
@ 2016-05-18  8:41     ` Tahhan, Maryam
  1 sibling, 0 replies; 71+ messages in thread
From: Tahhan, Maryam @ 2016-05-18  8:41 UTC (permalink / raw)
  To: Horton, Remy, dev

> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Remy Horton
> Sent: Friday, May 6, 2016 12:11 PM
> To: dev@dpdk.org
> Subject: [dpdk-dev] [RFC PATCH v2 2/3] drivers/net/ixgbe: change xstats
> to use integer id
> 
> Signed-off-by: Remy Horton <remy.horton@intel.com>
> ---

Acked-by: Maryam Tahhan <maryam.tahhan@intel.com>

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

* Re: [RFC PATCH v2 3/3] examples/ethtool: add xstats display command
  2016-05-06 11:11   ` [RFC PATCH v2 3/3] examples/ethtool: add xstats display command Remy Horton
  2016-05-09 14:08     ` David Harton (dharton)
@ 2016-05-18  8:42     ` Tahhan, Maryam
  1 sibling, 0 replies; 71+ messages in thread
From: Tahhan, Maryam @ 2016-05-18  8:42 UTC (permalink / raw)
  To: Horton, Remy, dev

> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Remy Horton
> Sent: Friday, May 6, 2016 12:11 PM
> To: dev@dpdk.org
> Subject: [dpdk-dev] [RFC PATCH v2 3/3] examples/ethtool: add xstats
> display command
> 
> Signed-off-by: Remy Horton <remy.horton@intel.com>
> ---
Acked-by: Maryam Tahhan <maryam.tahhan@intel.com>

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

* Re: [RFC PATCH v2 1/3] rte: change xstats to use integer keys
  2016-05-18  8:31     ` Tahhan, Maryam
@ 2016-05-18  8:45       ` Remy Horton
  0 siblings, 0 replies; 71+ messages in thread
From: Remy Horton @ 2016-05-18  8:45 UTC (permalink / raw)
  To: Tahhan, Maryam, dev


On 18/05/2016 09:31, Tahhan, Maryam wrote:
[..]
>> +	eth_xstats_count_t         xstats_count;
>> +	/**< Get number of extended statistics. */
>
> Hi Remy
> While reviewing the second patch in this patchset I noticed you aren't actually using
> eth_xstats_count_t   xstats_count in the eth_dev_ops to retrieve the count in the driver.
> Do you still need xstats_count?

Well spotted - bit of dead code that slipped through the net when I 
decided to use the existing convention for the driver-side interface.

Currently working on a v3 that will convert all the drivers, so will fix 
in that patchset.

..Remy

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

* Re: [RFC PATCH v2 0/3] Remove string operations from xstats
  2016-05-16 10:42   ` [RFC PATCH v2 0/3] Remove string operations from xstats Tahhan, Maryam
@ 2016-05-18 10:12     ` Remy Horton
  0 siblings, 0 replies; 71+ messages in thread
From: Remy Horton @ 2016-05-18 10:12 UTC (permalink / raw)
  To: Tahhan, Maryam, dev


On 16/05/2016 11:42, Tahhan, Maryam wrote:
[..]
>
> Looks Great overall. Is there a need to update prog_guide/poll_mode_drv.rst with the new mods?

Yes it will need updating, as the description of rte_eth_xstats is now 
incorrect. Will fix in v3..

..Remy

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

* [PATCH v3 00/10] Remove string operations from xstats
  2016-05-06 11:11 ` [RFC PATCH v2 " Remy Horton
                     ` (3 preceding siblings ...)
  2016-05-16 10:42   ` [RFC PATCH v2 0/3] Remove string operations from xstats Tahhan, Maryam
@ 2016-05-30 10:48   ` Remy Horton
  2016-05-30 10:48     ` [PATCH v3 01/10] rte: change xstats to use integer ids Remy Horton
                       ` (11 more replies)
  4 siblings, 12 replies; 71+ messages in thread
From: Remy Horton @ 2016-05-30 10:48 UTC (permalink / raw)
  To: dev, Thomas Monjalon, Helin Zhang, Wenzhuo Lu, Jing Chen, Huawei Xie

The current extended ethernet statistics fetching involve doing several
string operations, which causes performance issues if there are lots of
statistics and/or network interfaces. This patchset changes the API for
xstats to use integer identifiers instead of strings and implements
this new API for the ixgbe, i40e, e1000, fm10k, and virtio drivers.

--

v3 changes:
* Corrected ixgbe vf xstats fetching
* Added xstats changes to e1000, f10k, and virtio drivers
* Added cleanup patch that removes now-redundant name field
* Removed ethtool xstats command 
* Removed unused .xstats_count from eth-dev_ops
* Changed test-pmd & proc_info to use new API
* Added documentation update
* Added missing changes to .map file (affected shared lib builds)

v2 changes:
* Fetching xstats count now seperate API function
* Added #define constants for some magic numbers
* Fixed bug with virtual function count fetching
* For non-xstats-supporting drivers, queue stats returned
* Some refactoring/cleanups
* Removed index assumption from example

Remy Horton (10):
  rte: change xstats to use integer ids
  drivers/net/ixgbe: change xstats to use integer ids
  drivers/net/e1000: change xstats to use integer ids
  drivers/net/fm10k: change xstats to use integer ids
  drivers/net/i40e: change xstats to use integer ids
  drivers/net/virtio: change xstats to use integer ids
  app/test-pmd: change xstats to use integer ids
  app/proc_info: change xstats to use integer ids
  remove name field from struct rte_eth_xstats
  doc: update xstats documentation

 app/proc_info/main.c                    | 26 ++++++++-
 app/test-pmd/config.c                   | 52 +++++++++++++----
 doc/guides/prog_guide/poll_mode_drv.rst | 25 +++++++--
 drivers/net/e1000/igb_ethdev.c          | 50 +++++++++++++++--
 drivers/net/fm10k/fm10k_ethdev.c        | 52 ++++++++++++++---
 drivers/net/i40e/i40e_ethdev.c          | 77 +++++++++++++++++++++-----
 drivers/net/i40e/i40e_ethdev_vf.c       | 24 +++++++-
 drivers/net/ixgbe/ixgbe_ethdev.c        | 98 ++++++++++++++++++++++++++++-----
 drivers/net/virtio/virtio_ethdev.c      | 60 +++++++++++++++++---
 lib/librte_ether/rte_ethdev.c           | 92 ++++++++++++++++++++++++++++---
 lib/librte_ether/rte_ethdev.h           | 44 ++++++++++++++-
 lib/librte_ether/rte_ether_version.map  |  7 +++
 12 files changed, 527 insertions(+), 80 deletions(-)

-- 
2.5.5

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

* [PATCH v3 01/10] rte: change xstats to use integer ids
  2016-05-30 10:48   ` [PATCH v3 00/10] " Remy Horton
@ 2016-05-30 10:48     ` Remy Horton
  2016-06-08  9:37       ` Thomas Monjalon
  2016-05-30 10:48     ` [PATCH v3 02/10] drivers/net/ixgbe: " Remy Horton
                       ` (10 subsequent siblings)
  11 siblings, 1 reply; 71+ messages in thread
From: Remy Horton @ 2016-05-30 10:48 UTC (permalink / raw)
  To: dev, Thomas Monjalon

The current extended ethernet statistics fetching involve doing several
string operations, which causes performance issues if there are lots of
statistics and/or network interfaces. This patch changes the API for
xstats to use integer identifiers instead of strings.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 lib/librte_ether/rte_ethdev.c          | 95 +++++++++++++++++++++++++++++++---
 lib/librte_ether/rte_ethdev.h          | 44 ++++++++++++++++
 lib/librte_ether/rte_ether_version.map |  7 +++
 3 files changed, 138 insertions(+), 8 deletions(-)

diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index e148028..86fb0bc 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -1502,6 +1502,87 @@ rte_eth_stats_reset(uint8_t port_id)
 	dev->data->rx_mbuf_alloc_failed = 0;
 }
 
+int
+rte_eth_xstats_count(uint8_t port_id)
+{
+	struct rte_eth_dev *dev;
+	int count;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL);
+	dev = &rte_eth_devices[port_id];
+	if (dev->dev_ops->xstats_names != NULL) {
+		count = (*dev->dev_ops->xstats_names)(dev, NULL, 0);
+		if (count < 0)
+			return count;
+	} else
+		count = 0;
+	count += RTE_NB_STATS;
+	count += dev->data->nb_rx_queues * RTE_NB_RXQ_STATS;
+	count += dev->data->nb_tx_queues * RTE_NB_TXQ_STATS;
+	return count;
+}
+
+int
+rte_eth_xstats_names(uint8_t port_id, struct rte_eth_xstats_name *ptr_names,
+	unsigned limit)
+{
+	struct rte_eth_dev *dev;
+	int cnt_used_entries;
+	int cnt_expected_entries;
+	uint32_t idx, id_queue;
+
+	if (ptr_names == NULL)
+		return -EINVAL;
+	cnt_expected_entries = rte_eth_xstats_count(port_id);
+	if (cnt_expected_entries < 0)
+		return cnt_expected_entries;
+	if ((int)limit < cnt_expected_entries)
+		return -ERANGE;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL);
+	dev = &rte_eth_devices[port_id];
+	if (dev->dev_ops->xstats_names != NULL) {
+		cnt_used_entries = (*dev->dev_ops->xstats_names)(
+			dev, ptr_names, limit);
+		if (cnt_used_entries < 0)
+			return cnt_used_entries;
+	} else
+		/* Driver itself does not support extended stats, but
+		 * still have basic stats.
+		 */
+		cnt_used_entries = 0;
+
+	for (idx = 0; idx < RTE_NB_STATS; idx++) {
+		ptr_names[cnt_used_entries].id = cnt_used_entries;
+		snprintf(ptr_names[cnt_used_entries].name,
+			sizeof(ptr_names[0].name),
+			"%s", rte_stats_strings[idx].name);
+		cnt_used_entries++;
+	}
+	for (id_queue = 0; id_queue < dev->data->nb_rx_queues; id_queue++) {
+		for (idx = 0; idx < RTE_NB_RXQ_STATS; idx++) {
+			ptr_names[cnt_used_entries].id = cnt_used_entries;
+			snprintf(ptr_names[cnt_used_entries].name,
+				sizeof(ptr_names[0].name),
+				"rx_q%u%s",
+				id_queue, rte_rxq_stats_strings[idx].name);
+			cnt_used_entries++;
+		}
+
+	}
+	for (id_queue = 0; id_queue < dev->data->nb_tx_queues; id_queue++) {
+		for (idx = 0; idx < RTE_NB_TXQ_STATS; idx++) {
+			ptr_names[cnt_used_entries].id = cnt_used_entries;
+			snprintf(ptr_names[cnt_used_entries].name,
+				sizeof(ptr_names[0].name),
+				"tx_q%u%s",
+				id_queue, rte_txq_stats_strings[idx].name);
+			cnt_used_entries++;
+		}
+	}
+	return cnt_used_entries;
+}
+
 /* retrieve ethdev extended statistics */
 int
 rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
@@ -1546,8 +1627,8 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
 		stats_ptr = RTE_PTR_ADD(&eth_stats,
 					rte_stats_strings[i].offset);
 		val = *stats_ptr;
-		snprintf(xstats[count].name, sizeof(xstats[count].name),
-			"%s", rte_stats_strings[i].name);
+		xstats[count].name[0] = '\0';
+		xstats[count].id = count + xcount;
 		xstats[count++].value = val;
 	}
 
@@ -1558,9 +1639,8 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
 					rte_rxq_stats_strings[i].offset +
 					q * sizeof(uint64_t));
 			val = *stats_ptr;
-			snprintf(xstats[count].name, sizeof(xstats[count].name),
-				"rx_q%u_%s", q,
-				rte_rxq_stats_strings[i].name);
+			xstats[count].name[0] = '\0';
+			xstats[count].id = count + xcount;
 			xstats[count++].value = val;
 		}
 	}
@@ -1572,9 +1652,8 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
 					rte_txq_stats_strings[i].offset +
 					q * sizeof(uint64_t));
 			val = *stats_ptr;
-			snprintf(xstats[count].name, sizeof(xstats[count].name),
-				"tx_q%u_%s", q,
-				rte_txq_stats_strings[i].name);
+			xstats[count].name[0] = '\0';
+			xstats[count].id = count + xcount;
 			xstats[count++].value = val;
 		}
 	}
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 2757510..d663d60 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -915,10 +915,23 @@ struct rte_eth_txq_info {
  * structure.
  */
 struct rte_eth_xstats {
+	/* FIXME: Remove name[] once remaining drivers converted */
 	char name[RTE_ETH_XSTATS_NAME_SIZE];
+	uint64_t id;
 	uint64_t value;
 };
 
+/**
+ * A name-key lookup element for extended statistics.
+ *
+ * This structure is used to map between names and ID numbers
+ * for extended ethernet statistics.
+ */
+struct rte_eth_xstats_name {
+	char name[RTE_ETH_XSTATS_NAME_SIZE];
+	uint64_t id;
+};
+
 #define ETH_DCB_NUM_TCS    8
 #define ETH_MAX_VMDQ_POOL  64
 
@@ -1054,6 +1067,10 @@ typedef int (*eth_xstats_get_t)(struct rte_eth_dev *dev,
 typedef void (*eth_xstats_reset_t)(struct rte_eth_dev *dev);
 /**< @internal Reset extended stats of an Ethernet device. */
 
+typedef int (*eth_xstats_names_t)(struct rte_eth_dev *dev,
+	struct rte_eth_xstats_name *ptr_names, unsigned limit);
+/**< @internal Get names of extended stats of an Ethernet device. */
+
 typedef int (*eth_queue_stats_mapping_set_t)(struct rte_eth_dev *dev,
 					     uint16_t queue_id,
 					     uint8_t stat_idx,
@@ -1401,6 +1418,8 @@ struct eth_dev_ops {
 	eth_stats_reset_t          stats_reset;   /**< Reset generic device statistics. */
 	eth_xstats_get_t           xstats_get;    /**< Get extended device statistics. */
 	eth_xstats_reset_t         xstats_reset;  /**< Reset extended device statistics. */
+	eth_xstats_names_t         xstats_names;
+	/**< Get names of extended statistics. */
 	eth_queue_stats_mapping_set_t queue_stats_mapping_set;
 	/**< Configure per queue stat counter mapping. */
 	eth_dev_infos_get_t        dev_infos_get; /**< Get device info. */
@@ -2253,6 +2272,31 @@ int rte_eth_stats_get(uint8_t port_id, struct rte_eth_stats *stats);
 void rte_eth_stats_reset(uint8_t port_id);
 
 /**
+ * Retrieve names of extended statistics of an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param ptr_names
+ *  Block of memory to insert names into. Must be at least limit in size.
+ * @param limit
+ *  Capacity of ptr_strings (number of names).
+ * @return
+ *  If successful, number of statistics; negative on error.
+ */
+int rte_eth_xstats_names(uint8_t port_id, struct rte_eth_xstats_name *ptr_names,
+	unsigned limit);
+
+/**
+ * Retrieve number of extended statistics of an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @return
+ *  If successful, number of statistics; negative on error.
+ */
+int rte_eth_xstats_count(uint8_t port_id);
+
+/**
  * Retrieve 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 214ecc7..bb339e1 100644
--- a/lib/librte_ether/rte_ether_version.map
+++ b/lib/librte_ether/rte_ether_version.map
@@ -132,3 +132,10 @@ DPDK_16.04 {
 	rte_eth_tx_buffer_set_err_callback;
 
 } DPDK_2.2;
+
+DPDK_16.07 {
+	global:
+
+	rte_eth_xstats_names;
+	rte_eth_xstats_count;
+} DPDK_16.04;
-- 
2.5.5

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

* [PATCH v3 02/10] drivers/net/ixgbe: change xstats to use integer ids
  2016-05-30 10:48   ` [PATCH v3 00/10] " Remy Horton
  2016-05-30 10:48     ` [PATCH v3 01/10] rte: change xstats to use integer ids Remy Horton
@ 2016-05-30 10:48     ` Remy Horton
  2016-05-30 10:48     ` [PATCH v3 03/10] drivers/net/e1000: " Remy Horton
                       ` (9 subsequent siblings)
  11 siblings, 0 replies; 71+ messages in thread
From: Remy Horton @ 2016-05-30 10:48 UTC (permalink / raw)
  To: dev, Helin Zhang

The current extended ethernet statistics fetching involve doing several
string operations, which causes performance issues if there are lots of
statistics and/or network interfaces. This patch changes the ixgbe driver
to use the new API that seperates name string and value queries.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 drivers/net/ixgbe/ixgbe_ethdev.c | 101 +++++++++++++++++++++++++++++++++------
 1 file changed, 86 insertions(+), 15 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index a2b170b..bb5940b 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -179,6 +179,10 @@ static int ixgbevf_dev_xstats_get(struct rte_eth_dev *dev,
 				  struct rte_eth_xstats *xstats, unsigned n);
 static void ixgbe_dev_stats_reset(struct rte_eth_dev *dev);
 static void ixgbe_dev_xstats_reset(struct rte_eth_dev *dev);
+static int ixgbe_dev_xstats_names(__rte_unused struct rte_eth_dev *dev,
+	struct rte_eth_xstats_name *ptr_names, __rte_unused unsigned limit);
+static int ixgbevf_dev_xstats_names(__rte_unused struct rte_eth_dev *dev,
+	struct rte_eth_xstats_name *ptr_names, __rte_unused unsigned limit);
 static int ixgbe_dev_queue_stats_mapping_set(struct rte_eth_dev *eth_dev,
 					     uint16_t queue_id,
 					     uint8_t stat_idx,
@@ -466,6 +470,7 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = {
 	.xstats_get           = ixgbe_dev_xstats_get,
 	.stats_reset          = ixgbe_dev_stats_reset,
 	.xstats_reset         = ixgbe_dev_xstats_reset,
+	.xstats_names         = ixgbe_dev_xstats_names,
 	.queue_stats_mapping_set = ixgbe_dev_queue_stats_mapping_set,
 	.dev_infos_get        = ixgbe_dev_info_get,
 	.dev_supported_ptypes_get = ixgbe_dev_supported_ptypes_get,
@@ -555,6 +560,7 @@ static const struct eth_dev_ops ixgbevf_eth_dev_ops = {
 	.xstats_get           = ixgbevf_dev_xstats_get,
 	.stats_reset          = ixgbevf_dev_stats_reset,
 	.xstats_reset         = ixgbevf_dev_stats_reset,
+	.xstats_names         = ixgbevf_dev_xstats_names,
 	.dev_close            = ixgbevf_dev_close,
 	.allmulticast_enable  = ixgbevf_dev_allmulticast_enable,
 	.allmulticast_disable = ixgbevf_dev_allmulticast_disable,
@@ -685,6 +691,7 @@ static const struct rte_ixgbe_xstats_name_off rte_ixgbe_rxq_strings[] = {
 
 #define IXGBE_NB_RXQ_PRIO_STATS (sizeof(rte_ixgbe_rxq_strings) / \
 			   sizeof(rte_ixgbe_rxq_strings[0]))
+#define IXGBE_NB_RXQ_PRIO_VALUES 8
 
 static const struct rte_ixgbe_xstats_name_off rte_ixgbe_txq_strings[] = {
 	{"xon_packets", offsetof(struct ixgbe_hw_stats, pxontxc)},
@@ -695,6 +702,7 @@ static const struct rte_ixgbe_xstats_name_off rte_ixgbe_txq_strings[] = {
 
 #define IXGBE_NB_TXQ_PRIO_STATS (sizeof(rte_ixgbe_txq_strings) / \
 			   sizeof(rte_ixgbe_txq_strings[0]))
+#define IXGBE_NB_TXQ_PRIO_VALUES 8
 
 static const struct rte_ixgbe_xstats_name_off rte_ixgbevf_stats_strings[] = {
 	{"rx_multicast_packets", offsetof(struct ixgbevf_hw_stats, vfmprc)},
@@ -2695,8 +2703,75 @@ ixgbe_dev_stats_reset(struct rte_eth_dev *dev)
 /* This function calculates the number of xstats based on the current config */
 static unsigned
 ixgbe_xstats_calc_num(void) {
-	return IXGBE_NB_HW_STATS + (IXGBE_NB_RXQ_PRIO_STATS * 8) +
-		(IXGBE_NB_TXQ_PRIO_STATS * 8);
+	return IXGBE_NB_HW_STATS +
+		(IXGBE_NB_RXQ_PRIO_STATS * IXGBE_NB_RXQ_PRIO_VALUES) +
+		(IXGBE_NB_TXQ_PRIO_STATS * IXGBE_NB_TXQ_PRIO_VALUES);
+}
+
+static int ixgbe_dev_xstats_names(__rte_unused struct rte_eth_dev *dev,
+	struct rte_eth_xstats_name *ptr_names, __rte_unused unsigned limit)
+{
+	const unsigned cnt_stats = ixgbe_xstats_calc_num();
+	unsigned stat, i, count;
+
+	if (ptr_names != NULL) {
+		count = 0;
+
+		/* Note: limit >= cnt_stats checked upstream
+		 * in rte_eth_xstats_names()
+		 */
+
+		/* Extended stats from ixgbe_hw_stats */
+		for (i = 0; i < IXGBE_NB_HW_STATS; i++) {
+			ptr_names[count].id = count;
+			snprintf(ptr_names[count].name,
+				sizeof(ptr_names[count].name),
+				"%s",
+				rte_ixgbe_stats_strings[i].name);
+			count++;
+		}
+
+		/* RX Priority Stats */
+		for (stat = 0; stat < IXGBE_NB_RXQ_PRIO_STATS; stat++) {
+			for (i = 0; i < IXGBE_NB_RXQ_PRIO_VALUES; i++) {
+				ptr_names[count].id = count;
+				snprintf(ptr_names[count].name,
+					sizeof(ptr_names[count].name),
+					"rx_priority%u_%s", i,
+					rte_ixgbe_rxq_strings[stat].name);
+				count++;
+			}
+		}
+
+		/* TX Priority Stats */
+		for (stat = 0; stat < IXGBE_NB_TXQ_PRIO_STATS; stat++) {
+			for (i = 0; i < IXGBE_NB_TXQ_PRIO_VALUES; i++) {
+				ptr_names[count].id = count;
+				snprintf(ptr_names[count].name,
+					sizeof(ptr_names[count].name),
+					"tx_priority%u_%s", i,
+					rte_ixgbe_txq_strings[stat].name);
+				count++;
+			}
+		}
+	}
+	return cnt_stats;
+}
+
+static int ixgbevf_dev_xstats_names(__rte_unused struct rte_eth_dev *dev,
+	struct rte_eth_xstats_name *ptr_names, unsigned limit)
+{
+	unsigned i;
+
+	if (limit < IXGBEVF_NB_XSTATS && ptr_names != NULL)
+		return -ENOMEM;
+
+	if (ptr_names != NULL)
+		for (i = 0; i < IXGBEVF_NB_XSTATS; i++)
+			snprintf(ptr_names[i].name,
+				sizeof(ptr_names[i].name),
+				"%s", rte_ixgbevf_stats_strings[i].name);
+	return IXGBEVF_NB_XSTATS;
 }
 
 static int
@@ -2732,8 +2807,8 @@ ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 	/* Extended stats from ixgbe_hw_stats */
 	count = 0;
 	for (i = 0; i < IXGBE_NB_HW_STATS; i++) {
-		snprintf(xstats[count].name, sizeof(xstats[count].name), "%s",
-			 rte_ixgbe_stats_strings[i].name);
+		xstats[count].id = count;
+		xstats[count].name[0] = '\0';
 		xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
 				rte_ixgbe_stats_strings[i].offset);
 		count++;
@@ -2741,10 +2816,9 @@ ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 
 	/* RX Priority Stats */
 	for (stat = 0; stat < IXGBE_NB_RXQ_PRIO_STATS; stat++) {
-		for (i = 0; i < 8; i++) {
-			snprintf(xstats[count].name, sizeof(xstats[count].name),
-				 "rx_priority%u_%s", i,
-				 rte_ixgbe_rxq_strings[stat].name);
+		for (i = 0; i < IXGBE_NB_RXQ_PRIO_VALUES; i++) {
+			xstats[count].id = count;
+			xstats[count].name[0] = '\0';
 			xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
 					rte_ixgbe_rxq_strings[stat].offset +
 					(sizeof(uint64_t) * i));
@@ -2754,17 +2828,15 @@ ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 
 	/* TX Priority Stats */
 	for (stat = 0; stat < IXGBE_NB_TXQ_PRIO_STATS; stat++) {
-		for (i = 0; i < 8; i++) {
-			snprintf(xstats[count].name, sizeof(xstats[count].name),
-				 "tx_priority%u_%s", i,
-				 rte_ixgbe_txq_strings[stat].name);
+		for (i = 0; i < IXGBE_NB_TXQ_PRIO_VALUES; i++) {
+			xstats[count].id = count;
+			xstats[count].name[0] = '\0';
 			xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
 					rte_ixgbe_txq_strings[stat].offset +
 					(sizeof(uint64_t) * i));
 			count++;
 		}
 	}
-
 	return count;
 }
 
@@ -2829,8 +2901,7 @@ ixgbevf_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 
 	/* Extended stats */
 	for (i = 0; i < IXGBEVF_NB_XSTATS; i++) {
-		snprintf(xstats[i].name, sizeof(xstats[i].name),
-			 "%s", rte_ixgbevf_stats_strings[i].name);
+		xstats[i].id = i;
 		xstats[i].value = *(uint64_t *)(((char *)hw_stats) +
 			rte_ixgbevf_stats_strings[i].offset);
 	}
-- 
2.5.5

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

* [PATCH v3 03/10] drivers/net/e1000: change xstats to use integer ids
  2016-05-30 10:48   ` [PATCH v3 00/10] " Remy Horton
  2016-05-30 10:48     ` [PATCH v3 01/10] rte: change xstats to use integer ids Remy Horton
  2016-05-30 10:48     ` [PATCH v3 02/10] drivers/net/ixgbe: " Remy Horton
@ 2016-05-30 10:48     ` Remy Horton
  2016-05-30 10:48     ` [PATCH v3 04/10] drivers/net/fm10k: " Remy Horton
                       ` (8 subsequent siblings)
  11 siblings, 0 replies; 71+ messages in thread
From: Remy Horton @ 2016-05-30 10:48 UTC (permalink / raw)
  To: dev, Wenzhuo Lu

The current extended ethernet statistics fetching involve doing several
string operations, which causes performance issues if there are lots of
statistics and/or network interfaces. This patch changes the e1000 driver
to use the new API that seperates name string and value queries.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 drivers/net/e1000/igb_ethdev.c | 52 ++++++++++++++++++++++++++++++++++++++----
 1 file changed, 48 insertions(+), 4 deletions(-)

diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index f0921ee..6d5e46f 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -100,6 +100,9 @@ static void eth_igb_stats_get(struct rte_eth_dev *dev,
 				struct rte_eth_stats *rte_stats);
 static int eth_igb_xstats_get(struct rte_eth_dev *dev,
 			      struct rte_eth_xstats *xstats, unsigned n);
+static int eth_igb_xstats_names(struct rte_eth_dev *dev,
+				struct rte_eth_xstats_name *ptr_names,
+				unsigned limit);
 static void eth_igb_stats_reset(struct rte_eth_dev *dev);
 static void eth_igb_xstats_reset(struct rte_eth_dev *dev);
 static void eth_igb_infos_get(struct rte_eth_dev *dev,
@@ -165,6 +168,9 @@ static void eth_igbvf_stats_get(struct rte_eth_dev *dev,
 				struct rte_eth_stats *rte_stats);
 static int eth_igbvf_xstats_get(struct rte_eth_dev *dev,
 				struct rte_eth_xstats *xstats, unsigned n);
+static int eth_igbvf_xstats_names(struct rte_eth_dev *dev,
+				  struct rte_eth_xstats_name *ptr_names,
+				  unsigned limit);
 static void eth_igbvf_stats_reset(struct rte_eth_dev *dev);
 static int igbvf_vlan_filter_set(struct rte_eth_dev *dev,
 		uint16_t vlan_id, int on);
@@ -324,6 +330,7 @@ static const struct eth_dev_ops eth_igb_ops = {
 	.link_update          = eth_igb_link_update,
 	.stats_get            = eth_igb_stats_get,
 	.xstats_get           = eth_igb_xstats_get,
+	.xstats_names         = eth_igb_xstats_names,
 	.stats_reset          = eth_igb_stats_reset,
 	.xstats_reset         = eth_igb_xstats_reset,
 	.dev_infos_get        = eth_igb_infos_get,
@@ -385,6 +392,7 @@ static const struct eth_dev_ops igbvf_eth_dev_ops = {
 	.link_update          = eth_igb_link_update,
 	.stats_get            = eth_igbvf_stats_get,
 	.xstats_get           = eth_igbvf_xstats_get,
+	.xstats_names         = eth_igbvf_xstats_names,
 	.stats_reset          = eth_igbvf_stats_reset,
 	.xstats_reset         = eth_igbvf_stats_reset,
 	.vlan_filter_set      = igbvf_vlan_filter_set,
@@ -1691,6 +1699,26 @@ eth_igb_xstats_reset(struct rte_eth_dev *dev)
 	memset(stats, 0, sizeof(*stats));
 }
 
+static int eth_igb_xstats_names(__rte_unused struct rte_eth_dev *dev,
+	struct rte_eth_xstats_name *ptr_names,
+	__rte_unused unsigned limit)
+{
+	unsigned i;
+
+	if (ptr_names == NULL)
+		return IGB_NB_XSTATS;
+
+	/* Note: limit checked in rte_eth_xstats_names() */
+
+	for (i = 0; i < IGB_NB_XSTATS; i++) {
+		snprintf(ptr_names[i].name, sizeof(ptr_names[i].name),
+			 "%s", rte_igb_stats_strings[i].name);
+		ptr_names[i].id = i;
+	}
+
+	return IGB_NB_XSTATS;
+}
+
 static int
 eth_igb_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 		   unsigned n)
@@ -1713,8 +1741,8 @@ eth_igb_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 
 	/* Extended stats */
 	for (i = 0; i < IGB_NB_XSTATS; i++) {
-		snprintf(xstats[i].name, sizeof(xstats[i].name),
-			 "%s", rte_igb_stats_strings[i].name);
+		xstats[i].name[0] = '\0';
+		xstats[i].id = i;
 		xstats[i].value = *(uint64_t *)(((char *)hw_stats) +
 			rte_igb_stats_strings[i].offset);
 	}
@@ -1762,6 +1790,22 @@ igbvf_read_stats_registers(struct e1000_hw *hw, struct e1000_vf_stats *hw_stats)
 	    hw_stats->last_gotlbc, hw_stats->gotlbc);
 }
 
+static int eth_igbvf_xstats_names(__rte_unused struct rte_eth_dev *dev,
+				  struct rte_eth_xstats_name *ptr_names,
+				  __rte_unused unsigned limit)
+{
+	unsigned i;
+
+	if (ptr_names != NULL)
+		for (i = 0; i < IGBVF_NB_XSTATS; i++) {
+			snprintf(ptr_names[i].name,
+				sizeof(ptr_names[i].name), "%s",
+				rte_igbvf_stats_strings[i].name);
+			ptr_names[i].id = i;
+		}
+	return IGBVF_NB_XSTATS;
+}
+
 static int
 eth_igbvf_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 		     unsigned n)
@@ -1780,8 +1824,8 @@ eth_igbvf_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 		return 0;
 
 	for (i = 0; i < IGBVF_NB_XSTATS; i++) {
-		snprintf(xstats[i].name, sizeof(xstats[i].name), "%s",
-			 rte_igbvf_stats_strings[i].name);
+		xstats[i].name[0] = '\0';
+		xstats[i].id = i;
 		xstats[i].value = *(uint64_t *)(((char *)hw_stats) +
 			rte_igbvf_stats_strings[i].offset);
 	}
-- 
2.5.5

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

* [PATCH v3 04/10] drivers/net/fm10k: change xstats to use integer ids
  2016-05-30 10:48   ` [PATCH v3 00/10] " Remy Horton
                       ` (2 preceding siblings ...)
  2016-05-30 10:48     ` [PATCH v3 03/10] drivers/net/e1000: " Remy Horton
@ 2016-05-30 10:48     ` Remy Horton
  2016-05-30 10:48     ` [PATCH v3 05/10] drivers/net/i40e: " Remy Horton
                       ` (7 subsequent siblings)
  11 siblings, 0 replies; 71+ messages in thread
From: Remy Horton @ 2016-05-30 10:48 UTC (permalink / raw)
  To: dev, Jing Chen

The current extended ethernet statistics fetching involve doing several
string operations, which causes performance issues if there are lots of
statistics and/or network interfaces. This patch changes the fm10k driver
to use the new API that seperates name string and value queries.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 drivers/net/fm10k/fm10k_ethdev.c | 55 +++++++++++++++++++++++++++++++++-------
 1 file changed, 46 insertions(+), 9 deletions(-)

diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c
index c2d377f..179441d 100644
--- a/drivers/net/fm10k/fm10k_ethdev.c
+++ b/drivers/net/fm10k/fm10k_ethdev.c
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2013-2015 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2013-2016 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -1256,6 +1256,47 @@ fm10k_link_update(struct rte_eth_dev *dev,
 	return 0;
 }
 
+static int fm10k_xstats_names(__rte_unused struct rte_eth_dev *dev,
+	struct rte_eth_xstats_name *ptr_names, __rte_unused unsigned limit)
+{
+	unsigned i, q;
+	unsigned count = 0;
+
+	if (ptr_names != NULL) {
+		/* Note: limit checked in rte_eth_xstats_names() */
+
+		/* Global stats */
+		for (i = 0; i < FM10K_NB_HW_XSTATS; i++) {
+			snprintf(ptr_names[count].name,
+				sizeof(ptr_names[count].name),
+				"%s", fm10k_hw_stats_strings[count].name);
+			ptr_names[count].id = count;
+			count++;
+		}
+
+		/* PF queue stats */
+		for (q = 0; q < FM10K_MAX_QUEUES_PF; q++) {
+			for (i = 0; i < FM10K_NB_RX_Q_XSTATS; i++) {
+				snprintf(ptr_names[count].name,
+					sizeof(ptr_names[count].name),
+					"rx_q%u_%s", q,
+					fm10k_hw_stats_rx_q_strings[i].name);
+				ptr_names[count].id = count;
+				count++;
+			}
+			for (i = 0; i < FM10K_NB_TX_Q_XSTATS; i++) {
+				snprintf(ptr_names[count].name,
+					sizeof(ptr_names[count].name),
+					"tx_q%u_%s", q,
+					fm10k_hw_stats_tx_q_strings[i].name);
+				ptr_names[count].id = count;
+				count++;
+			}
+		}
+	}
+	return FM10K_NB_XSTATS;
+}
+
 static int
 fm10k_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 		 unsigned n)
@@ -1269,8 +1310,7 @@ fm10k_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 
 	/* Global stats */
 	for (i = 0; i < FM10K_NB_HW_XSTATS; i++) {
-		snprintf(xstats[count].name, sizeof(xstats[count].name),
-			 "%s", fm10k_hw_stats_strings[count].name);
+		xstats[count].name[0] = '\0';
 		xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
 			fm10k_hw_stats_strings[count].offset);
 		count++;
@@ -1279,18 +1319,14 @@ fm10k_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 	/* PF queue stats */
 	for (q = 0; q < FM10K_MAX_QUEUES_PF; q++) {
 		for (i = 0; i < FM10K_NB_RX_Q_XSTATS; i++) {
-			snprintf(xstats[count].name, sizeof(xstats[count].name),
-				 "rx_q%u_%s", q,
-				 fm10k_hw_stats_rx_q_strings[i].name);
+			xstats[count].name[0] = '\0';
 			xstats[count].value =
 				*(uint64_t *)(((char *)&hw_stats->q[q]) +
 				fm10k_hw_stats_rx_q_strings[i].offset);
 			count++;
 		}
 		for (i = 0; i < FM10K_NB_TX_Q_XSTATS; i++) {
-			snprintf(xstats[count].name, sizeof(xstats[count].name),
-				 "tx_q%u_%s", q,
-				 fm10k_hw_stats_tx_q_strings[i].name);
+			xstats[count].name[0] = '\0';
 			xstats[count].value =
 				*(uint64_t *)(((char *)&hw_stats->q[q]) +
 				fm10k_hw_stats_tx_q_strings[i].offset);
@@ -2629,6 +2665,7 @@ static const struct eth_dev_ops fm10k_eth_dev_ops = {
 	.allmulticast_disable   = fm10k_dev_allmulticast_disable,
 	.stats_get		= fm10k_stats_get,
 	.xstats_get		= fm10k_xstats_get,
+	.xstats_names		= fm10k_xstats_names,
 	.stats_reset		= fm10k_stats_reset,
 	.xstats_reset		= fm10k_stats_reset,
 	.link_update		= fm10k_link_update,
-- 
2.5.5

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

* [PATCH v3 05/10] drivers/net/i40e: change xstats to use integer ids
  2016-05-30 10:48   ` [PATCH v3 00/10] " Remy Horton
                       ` (3 preceding siblings ...)
  2016-05-30 10:48     ` [PATCH v3 04/10] drivers/net/fm10k: " Remy Horton
@ 2016-05-30 10:48     ` Remy Horton
  2016-05-30 10:48     ` [PATCH v3 06/10] drivers/net/virtio: " Remy Horton
                       ` (6 subsequent siblings)
  11 siblings, 0 replies; 71+ messages in thread
From: Remy Horton @ 2016-05-30 10:48 UTC (permalink / raw)
  To: dev, Helin Zhang

The current extended ethernet statistics fetching involve doing several
string operations, which causes performance issues if there are lots of
statistics and/or network interfaces. This patch changes the i40e driver
to use the new API that seperates name string and value queries.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c    | 81 ++++++++++++++++++++++++++++++++-------
 drivers/net/i40e/i40e_ethdev_vf.c | 25 ++++++++++--
 2 files changed, 89 insertions(+), 17 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 24777d5..e0ce695 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -306,6 +306,9 @@ static void i40e_dev_stats_get(struct rte_eth_dev *dev,
 			       struct rte_eth_stats *stats);
 static int i40e_dev_xstats_get(struct rte_eth_dev *dev,
 			       struct rte_eth_xstats *xstats, unsigned n);
+static int i40e_dev_xstats_names(struct rte_eth_dev *dev,
+				 struct rte_eth_xstats_name *ptr_names,
+				 unsigned limit);
 static void i40e_dev_stats_reset(struct rte_eth_dev *dev);
 static int i40e_dev_queue_stats_mapping_set(struct rte_eth_dev *dev,
 					    uint16_t queue_id,
@@ -467,6 +470,7 @@ static const struct eth_dev_ops i40e_eth_dev_ops = {
 	.link_update                  = i40e_dev_link_update,
 	.stats_get                    = i40e_dev_stats_get,
 	.xstats_get                   = i40e_dev_xstats_get,
+	.xstats_names                 = i40e_dev_xstats_names,
 	.stats_reset                  = i40e_dev_stats_reset,
 	.xstats_reset                 = i40e_dev_stats_reset,
 	.queue_stats_mapping_set      = i40e_dev_queue_stats_mapping_set,
@@ -2205,6 +2209,59 @@ i40e_xstats_calc_num(void)
 		(I40E_NB_TXQ_PRIO_XSTATS * 8);
 }
 
+static int i40e_dev_xstats_names(__rte_unused struct rte_eth_dev *dev,
+				 struct rte_eth_xstats_name *ptr_names,
+				 __rte_unused unsigned limit)
+{
+	unsigned count = 0;
+	unsigned i, prio;
+
+	if (ptr_names == NULL)
+		return i40e_xstats_calc_num();
+
+	/* Note: limit checked in rte_eth_xstats_names() */
+
+	/* Get stats from i40e_eth_stats struct */
+	for (i = 0; i < I40E_NB_ETH_XSTATS; i++) {
+		snprintf(ptr_names[count].name, sizeof(ptr_names[count].name),
+			 "%s", rte_i40e_stats_strings[i].name);
+		ptr_names[count].id = count;
+		count++;
+	}
+
+	/* Get individiual stats from i40e_hw_port struct */
+	for (i = 0; i < I40E_NB_HW_PORT_XSTATS; i++) {
+		snprintf(ptr_names[count].name,
+			sizeof(ptr_names[count].name),
+			 "%s", rte_i40e_hw_port_strings[i].name);
+		ptr_names[count].id = count;
+		count++;
+	}
+
+	for (i = 0; i < I40E_NB_RXQ_PRIO_XSTATS; i++) {
+		for (prio = 0; prio < 8; prio++) {
+			snprintf(ptr_names[count].name,
+				 sizeof(ptr_names[count].name),
+				 "rx_priority%u_%s", prio,
+				 rte_i40e_rxq_prio_strings[i].name);
+			ptr_names[count].id = count;
+			count++;
+		}
+	}
+
+	for (i = 0; i < I40E_NB_TXQ_PRIO_XSTATS; i++) {
+		for (prio = 0; prio < 8; prio++) {
+			snprintf(ptr_names[count].name,
+				 sizeof(ptr_names[count].name),
+				 "tx_priority%u_%s", prio,
+				 rte_i40e_txq_prio_strings[i].name);
+			ptr_names[count].id = count;
+			count++;
+		}
+	}
+	return count;
+}
+
 static int
 i40e_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 		    unsigned n)
@@ -2227,8 +2284,8 @@ i40e_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 
 	/* Get stats from i40e_eth_stats struct */
 	for (i = 0; i < I40E_NB_ETH_XSTATS; i++) {
-		snprintf(xstats[count].name, sizeof(xstats[count].name),
-			 "%s", rte_i40e_stats_strings[i].name);
+		xstats[count].name[0] = '\0';
+		xstats[count].id = count;
 		xstats[count].value = *(uint64_t *)(((char *)&hw_stats->eth) +
 			rte_i40e_stats_strings[i].offset);
 		count++;
@@ -2236,19 +2293,17 @@ i40e_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 
 	/* Get individiual stats from i40e_hw_port struct */
 	for (i = 0; i < I40E_NB_HW_PORT_XSTATS; i++) {
-		snprintf(xstats[count].name, sizeof(xstats[count].name),
-			 "%s", rte_i40e_hw_port_strings[i].name);
+		xstats[count].name[0] = '\0';
+		xstats[count].id = count;
 		xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
-				rte_i40e_hw_port_strings[i].offset);
+			rte_i40e_hw_port_strings[i].offset);
 		count++;
 	}
 
 	for (i = 0; i < I40E_NB_RXQ_PRIO_XSTATS; i++) {
 		for (prio = 0; prio < 8; prio++) {
-			snprintf(xstats[count].name,
-				 sizeof(xstats[count].name),
-				 "rx_priority%u_%s", prio,
-				 rte_i40e_rxq_prio_strings[i].name);
+			xstats[count].name[0] = '\0';
+			xstats[count].id = count;
 			xstats[count].value =
 				*(uint64_t *)(((char *)hw_stats) +
 				rte_i40e_rxq_prio_strings[i].offset +
@@ -2259,10 +2314,8 @@ i40e_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 
 	for (i = 0; i < I40E_NB_TXQ_PRIO_XSTATS; i++) {
 		for (prio = 0; prio < 8; prio++) {
-			snprintf(xstats[count].name,
-				 sizeof(xstats[count].name),
-				 "tx_priority%u_%s", prio,
-				 rte_i40e_txq_prio_strings[i].name);
+			xstats[count].name[0] = '\0';
+			xstats[count].id = count;
 			xstats[count].value =
 				*(uint64_t *)(((char *)hw_stats) +
 				rte_i40e_txq_prio_strings[i].offset +
diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
index 90682ac..c3301c5 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -112,6 +112,9 @@ static void i40evf_dev_stats_get(struct rte_eth_dev *dev,
 				struct rte_eth_stats *stats);
 static int i40evf_dev_xstats_get(struct rte_eth_dev *dev,
 				 struct rte_eth_xstats *xstats, unsigned n);
+static int i40evf_dev_xstats_names(struct rte_eth_dev *dev,
+				   struct rte_eth_xstats_name *ptr_names,
+				   unsigned limit);
 static void i40evf_dev_xstats_reset(struct rte_eth_dev *dev);
 static int i40evf_vlan_filter_set(struct rte_eth_dev *dev,
 				  uint16_t vlan_id, int on);
@@ -196,6 +199,7 @@ static const struct eth_dev_ops i40evf_eth_dev_ops = {
 	.link_update          = i40evf_dev_link_update,
 	.stats_get            = i40evf_dev_stats_get,
 	.xstats_get           = i40evf_dev_xstats_get,
+	.xstats_names         = i40evf_dev_xstats_names,
 	.xstats_reset         = i40evf_dev_xstats_reset,
 	.dev_close            = i40evf_dev_close,
 	.dev_infos_get        = i40evf_dev_info_get,
@@ -984,6 +988,21 @@ i40evf_dev_xstats_reset(struct rte_eth_dev *dev)
 	vf->vsi.eth_stats_offset = vf->vsi.eth_stats;
 }
 
+static int i40evf_dev_xstats_names(__rte_unused struct rte_eth_dev *dev,
+				   struct rte_eth_xstats_name *ptr_names,
+				   __rte_unused unsigned limit)
+{
+	unsigned i;
+
+	if (ptr_names != NULL)
+		for (i = 0; i < I40EVF_NB_XSTATS; i++) {
+			snprintf(ptr_names[i].name, sizeof(ptr_names[i].name),
+				"%s", rte_i40evf_stats_strings[i].name);
+			ptr_names[i].id = i;
+		}
+	return I40EVF_NB_XSTATS;
+}
+
 static int i40evf_dev_xstats_get(struct rte_eth_dev *dev,
 				 struct rte_eth_xstats *xstats, unsigned n)
 {
@@ -1003,8 +1022,8 @@ static int i40evf_dev_xstats_get(struct rte_eth_dev *dev,
 
 	/* loop over xstats array and values from pstats */
 	for (i = 0; i < I40EVF_NB_XSTATS; i++) {
-		snprintf(xstats[i].name, sizeof(xstats[i].name),
-			 "%s", rte_i40evf_stats_strings[i].name);
+		xstats[i].name[0] = '\0';
+		xstats[i].id = i;
 		xstats[i].value = *(uint64_t *)(((char *)pstats) +
 			rte_i40evf_stats_strings[i].offset);
 	}
-- 
2.5.5

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

* [PATCH v3 06/10] drivers/net/virtio: change xstats to use integer ids
  2016-05-30 10:48   ` [PATCH v3 00/10] " Remy Horton
                       ` (4 preceding siblings ...)
  2016-05-30 10:48     ` [PATCH v3 05/10] drivers/net/i40e: " Remy Horton
@ 2016-05-30 10:48     ` Remy Horton
  2016-05-30 10:48     ` [PATCH v3 07/10] app/test-pmd: " Remy Horton
                       ` (5 subsequent siblings)
  11 siblings, 0 replies; 71+ messages in thread
From: Remy Horton @ 2016-05-30 10:48 UTC (permalink / raw)
  To: dev, Huawei Xie

The current extended ethernet statistics fetching involve doing several
string operations, which causes performance issues if there are lots of
statistics and/or network interfaces. This patch changes the virtio driver
to use the new API that seperates name string and value queries.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 drivers/net/virtio/virtio_ethdev.c | 62 +++++++++++++++++++++++++++++++++-----
 1 file changed, 55 insertions(+), 7 deletions(-)

diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c
index c3fb628..9d549de 100644
--- a/drivers/net/virtio/virtio_ethdev.c
+++ b/drivers/net/virtio/virtio_ethdev.c
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -80,6 +80,9 @@ static void virtio_dev_stats_get(struct rte_eth_dev *dev,
 				 struct rte_eth_stats *stats);
 static int virtio_dev_xstats_get(struct rte_eth_dev *dev,
 				 struct rte_eth_xstats *xstats, unsigned n);
+static int virtio_dev_xstats_names(struct rte_eth_dev *dev,
+				   struct rte_eth_xstats_name *ptr_names,
+				   unsigned limit);
 static void virtio_dev_stats_reset(struct rte_eth_dev *dev);
 static void virtio_dev_free_mbufs(struct rte_eth_dev *dev);
 static int virtio_vlan_filter_set(struct rte_eth_dev *dev,
@@ -615,6 +618,7 @@ static const struct eth_dev_ops virtio_eth_dev_ops = {
 	.dev_infos_get           = virtio_dev_info_get,
 	.stats_get               = virtio_dev_stats_get,
 	.xstats_get              = virtio_dev_xstats_get,
+	.xstats_names            = virtio_dev_xstats_names,
 	.stats_reset             = virtio_dev_stats_reset,
 	.xstats_reset            = virtio_dev_stats_reset,
 	.link_update             = virtio_dev_link_update,
@@ -708,6 +712,52 @@ virtio_update_stats(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
 	stats->rx_nombuf = dev->data->rx_mbuf_alloc_failed;
 }
 
+static int virtio_dev_xstats_names(struct rte_eth_dev *dev,
+				   struct rte_eth_xstats_name *ptr_names,
+				   __rte_unused unsigned limit)
+{
+	unsigned i;
+	unsigned count = 0;
+	unsigned t;
+
+	unsigned nstats = dev->data->nb_tx_queues * VIRTIO_NB_Q_XSTATS +
+		dev->data->nb_rx_queues * VIRTIO_NB_Q_XSTATS;
+
+	if (ptr_names == NULL) {
+		/* Note: limit checked in rte_eth_xstats_names() */
+
+		for (i = 0; i < dev->data->nb_rx_queues; i++) {
+			struct virtqueue *rxvq = dev->data->rx_queues[i];
+			if (rxvq == NULL)
+				continue;
+			for (t = 0; t < VIRTIO_NB_Q_XSTATS; t++) {
+				snprintf(ptr_names[count].name,
+					sizeof(ptr_names[count].name),
+					"rx_q%u_%s", i,
+					rte_virtio_q_stat_strings[t].name);
+				ptr_names[count].id = count;
+				count++;
+			}
+		}
+
+		for (i = 0; i < dev->data->nb_tx_queues; i++) {
+			struct virtqueue *txvq = dev->data->tx_queues[i];
+			if (txvq == NULL)
+				continue;
+			for (t = 0; t < VIRTIO_NB_Q_XSTATS; t++) {
+				snprintf(ptr_names[count].name,
+					sizeof(ptr_names[count].name),
+					"tx_q%u_%s", i,
+					rte_virtio_q_stat_strings[t].name);
+				ptr_names[count].id = count;
+				count++;
+			}
+		}
+		return count;
+	}
+	return nstats;
+}
+
 static int
 virtio_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 		      unsigned n)
@@ -730,9 +780,8 @@ virtio_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 		unsigned t;
 
 		for (t = 0; t < VIRTIO_NB_Q_XSTATS; t++) {
-			snprintf(xstats[count].name, sizeof(xstats[count].name),
-				 "rx_q%u_%s", i,
-				 rte_virtio_q_stat_strings[t].name);
+			xstats[count].name[0] = '\0';
+			xstats[count].id = count;
 			xstats[count].value = *(uint64_t *)(((char *)rxvq) +
 				rte_virtio_q_stat_strings[t].offset);
 			count++;
@@ -748,9 +797,8 @@ virtio_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 		unsigned t;
 
 		for (t = 0; t < VIRTIO_NB_Q_XSTATS; t++) {
-			snprintf(xstats[count].name, sizeof(xstats[count].name),
-				 "tx_q%u_%s", i,
-				 rte_virtio_q_stat_strings[t].name);
+			xstats[count].name[0] = '\0';
+			xstats[count].id = count;
 			xstats[count].value = *(uint64_t *)(((char *)txvq) +
 				rte_virtio_q_stat_strings[t].offset);
 			count++;
-- 
2.5.5

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

* [PATCH v3 07/10] app/test-pmd: change xstats to use integer ids
  2016-05-30 10:48   ` [PATCH v3 00/10] " Remy Horton
                       ` (5 preceding siblings ...)
  2016-05-30 10:48     ` [PATCH v3 06/10] drivers/net/virtio: " Remy Horton
@ 2016-05-30 10:48     ` Remy Horton
  2016-05-30 10:48     ` [PATCH v3 08/10] app/proc_info: " Remy Horton
                       ` (4 subsequent siblings)
  11 siblings, 0 replies; 71+ messages in thread
From: Remy Horton @ 2016-05-30 10:48 UTC (permalink / raw)
  To: dev, Pablo de Lara

The current extended ethernet statistics fetching involve doing several
string operations, which causes performance issues if there are lots of
statistics and/or network interfaces. This patch changes the test-pmd
application to use the new API that seperates name string and value
queries.

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

diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 1c552e4..3ba5679 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -233,28 +233,56 @@ void
 nic_xstats_display(portid_t port_id)
 {
 	struct rte_eth_xstats *xstats;
-	int len, ret, i;
+	int cnt_xstats, idx_xstat, idx_name;
+	struct rte_eth_xstats_name *ptr_names;
 
 	printf("###### NIC extended statistics for port %-2d\n", port_id);
+	if (!rte_eth_dev_is_valid_port(port_id)) {
+		printf("Error: Invalid port number %i\n", port_id);
+		return;
+	}
+
+	/* Get count */
+	cnt_xstats = rte_eth_xstats_count(port_id);
+	if (cnt_xstats  < 0) {
+		printf("Error: Cannot get count of xstats\n");
+		return;
+	}
 
-	len = rte_eth_xstats_get(port_id, NULL, 0);
-	if (len < 0) {
-		printf("Cannot get xstats count\n");
+	/* Get id-name lookup table */
+	ptr_names = malloc(sizeof(struct rte_eth_xstats_name) * cnt_xstats);
+	if (ptr_names == NULL) {
+		printf("Cannot allocate memory for xstats lookup\n");
 		return;
 	}
-	xstats = malloc(sizeof(xstats[0]) * len);
+	if (cnt_xstats != rte_eth_xstats_names(
+			port_id, ptr_names, cnt_xstats)) {
+		printf("Error: Cannot get xstats lookup\n");
+		return;
+	}
+
+	/* Get stats themselves */
+	xstats = malloc(sizeof(struct rte_eth_xstats) * cnt_xstats);
 	if (xstats == NULL) {
 		printf("Cannot allocate memory for xstats\n");
+		free(ptr_names);
 		return;
 	}
-	ret = rte_eth_xstats_get(port_id, xstats, len);
-	if (ret < 0 || ret > len) {
-		printf("Cannot get xstats\n");
-		free(xstats);
+	if (cnt_xstats != rte_eth_xstats_get(port_id, xstats, cnt_xstats)) {
+		printf("Error: Unable to get xstats\n");
 		return;
 	}
-	for (i = 0; i < len; i++)
-		printf("%s: %"PRIu64"\n", xstats[i].name, xstats[i].value);
+
+	/* Display xstats */
+	for (idx_xstat = 0; idx_xstat < cnt_xstats; idx_xstat++)
+		for (idx_name = 0; idx_name < cnt_xstats; idx_name++)
+			if (ptr_names[idx_name].id == xstats[idx_xstat].id) {
+				printf("%s: %"PRIu64"\n",
+					ptr_names[idx_name].name,
+					xstats[idx_xstat].value);
+				break;
+			}
+	free(ptr_names);
 	free(xstats);
 }
 
-- 
2.5.5

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

* [PATCH v3 08/10] app/proc_info: change xstats to use integer ids
  2016-05-30 10:48   ` [PATCH v3 00/10] " Remy Horton
                       ` (6 preceding siblings ...)
  2016-05-30 10:48     ` [PATCH v3 07/10] app/test-pmd: " Remy Horton
@ 2016-05-30 10:48     ` Remy Horton
  2016-05-30 10:48     ` [PATCH v3 09/10] remove name field from struct rte_eth_xstats Remy Horton
                       ` (3 subsequent siblings)
  11 siblings, 0 replies; 71+ messages in thread
From: Remy Horton @ 2016-05-30 10:48 UTC (permalink / raw)
  To: dev, Maryam Tahhan

The current extended ethernet statistics fetching involve doing several
string operations, which causes performance issues if there are lots of
statistics and/or network interfaces. This patch changes the proc_info
application to use the new API that seperates name string and value
queries.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 app/proc_info/main.c | 26 +++++++++++++++++++++++---
 1 file changed, 23 insertions(+), 3 deletions(-)

diff --git a/app/proc_info/main.c b/app/proc_info/main.c
index 5f83092..ef71fcf 100644
--- a/app/proc_info/main.c
+++ b/app/proc_info/main.c
@@ -1,7 +1,7 @@
 /*
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -243,11 +243,13 @@ nic_stats_clear(uint8_t port_id)
 static void
 nic_xstats_display(uint8_t port_id)
 {
+	struct rte_eth_xstats_name *ptr_names;
 	struct rte_eth_xstats *xstats;
 	int len, ret, i;
+	int idx_name;
 	static const char *nic_stats_border = "########################";
 
-	len = rte_eth_xstats_get(port_id, NULL, 0);
+	len = rte_eth_xstats_count(port_id);
 	if (len < 0) {
 		printf("Cannot get xstats count\n");
 		return;
@@ -258,6 +260,18 @@ nic_xstats_display(uint8_t port_id)
 		return;
 	}
 
+	ptr_names = malloc(sizeof(struct rte_eth_xstats_name) * len);
+	if (ptr_names == NULL) {
+		printf("Cannot allocate memory for xstat names\n");
+		free(xstats);
+		return;
+	}
+	if (len != rte_eth_xstats_names(
+			port_id, ptr_names, len)) {
+		printf("Cannot get xstat names\n");
+		return;
+	}
+
 	printf("###### NIC extended statistics for port %-2d #########\n",
 			   port_id);
 	printf("%s############################\n",
@@ -270,11 +284,17 @@ nic_xstats_display(uint8_t port_id)
 	}
 
 	for (i = 0; i < len; i++)
-		printf("%s: %"PRIu64"\n", xstats[i].name, xstats[i].value);
+		for (idx_name = 0; idx_name < len; idx_name++)
+			if (ptr_names[idx_name].id == xstats[i].id) {
+				printf("%s: %lu\n", ptr_names[idx_name].name,
+					xstats[i].value);
+				break;
+			}
 
 	printf("%s############################\n",
 			   nic_stats_border);
 	free(xstats);
+	free(ptr_names);
 }
 
 static void
-- 
2.5.5

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

* [PATCH v3 09/10] remove name field from struct rte_eth_xstats
  2016-05-30 10:48   ` [PATCH v3 00/10] " Remy Horton
                       ` (7 preceding siblings ...)
  2016-05-30 10:48     ` [PATCH v3 08/10] app/proc_info: " Remy Horton
@ 2016-05-30 10:48     ` Remy Horton
  2016-06-08 12:23       ` Thomas Monjalon
  2016-05-30 10:48     ` [PATCH v3 10/10] doc: update xstats documentation Remy Horton
                       ` (2 subsequent siblings)
  11 siblings, 1 reply; 71+ messages in thread
From: Remy Horton @ 2016-05-30 10:48 UTC (permalink / raw)
  To: dev, Thomas Monjalon, Helin Zhang, Wenzhuo Lu, Jing Chen, Huawei Xie

The current extended ethernet statistics fetching involve doing several
string operations, which causes performance issues if there are lots of
statistics and/or network interfaces. This patch removes the name field
and all its usage of the old API.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 drivers/net/e1000/igb_ethdev.c     | 2 --
 drivers/net/fm10k/fm10k_ethdev.c   | 3 ---
 drivers/net/i40e/i40e_ethdev.c     | 4 ----
 drivers/net/i40e/i40e_ethdev_vf.c  | 1 -
 drivers/net/ixgbe/ixgbe_ethdev.c   | 3 ---
 drivers/net/virtio/virtio_ethdev.c | 2 --
 lib/librte_ether/rte_ethdev.c      | 3 ---
 lib/librte_ether/rte_ethdev.h      | 2 --
 8 files changed, 20 deletions(-)

diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index 6d5e46f..2bfd3f8 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -1741,7 +1741,6 @@ eth_igb_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 
 	/* Extended stats */
 	for (i = 0; i < IGB_NB_XSTATS; i++) {
-		xstats[i].name[0] = '\0';
 		xstats[i].id = i;
 		xstats[i].value = *(uint64_t *)(((char *)hw_stats) +
 			rte_igb_stats_strings[i].offset);
@@ -1824,7 +1823,6 @@ eth_igbvf_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 		return 0;
 
 	for (i = 0; i < IGBVF_NB_XSTATS; i++) {
-		xstats[i].name[0] = '\0';
 		xstats[i].id = i;
 		xstats[i].value = *(uint64_t *)(((char *)hw_stats) +
 			rte_igbvf_stats_strings[i].offset);
diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c
index 179441d..be7431d 100644
--- a/drivers/net/fm10k/fm10k_ethdev.c
+++ b/drivers/net/fm10k/fm10k_ethdev.c
@@ -1310,7 +1310,6 @@ fm10k_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 
 	/* Global stats */
 	for (i = 0; i < FM10K_NB_HW_XSTATS; i++) {
-		xstats[count].name[0] = '\0';
 		xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
 			fm10k_hw_stats_strings[count].offset);
 		count++;
@@ -1319,14 +1318,12 @@ fm10k_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 	/* PF queue stats */
 	for (q = 0; q < FM10K_MAX_QUEUES_PF; q++) {
 		for (i = 0; i < FM10K_NB_RX_Q_XSTATS; i++) {
-			xstats[count].name[0] = '\0';
 			xstats[count].value =
 				*(uint64_t *)(((char *)&hw_stats->q[q]) +
 				fm10k_hw_stats_rx_q_strings[i].offset);
 			count++;
 		}
 		for (i = 0; i < FM10K_NB_TX_Q_XSTATS; i++) {
-			xstats[count].name[0] = '\0';
 			xstats[count].value =
 				*(uint64_t *)(((char *)&hw_stats->q[q]) +
 				fm10k_hw_stats_tx_q_strings[i].offset);
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index e0ce695..cc77370 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -2284,7 +2284,6 @@ i40e_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 
 	/* Get stats from i40e_eth_stats struct */
 	for (i = 0; i < I40E_NB_ETH_XSTATS; i++) {
-		xstats[count].name[0] = '\0';
 		xstats[count].id = count;
 		xstats[count].value = *(uint64_t *)(((char *)&hw_stats->eth) +
 			rte_i40e_stats_strings[i].offset);
@@ -2293,7 +2292,6 @@ i40e_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 
 	/* Get individiual stats from i40e_hw_port struct */
 	for (i = 0; i < I40E_NB_HW_PORT_XSTATS; i++) {
-		xstats[count].name[0] = '\0';
 		xstats[count].id = count;
 		xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
 			rte_i40e_hw_port_strings[i].offset);
@@ -2302,7 +2300,6 @@ i40e_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 
 	for (i = 0; i < I40E_NB_RXQ_PRIO_XSTATS; i++) {
 		for (prio = 0; prio < 8; prio++) {
-			xstats[count].name[0] = '\0';
 			xstats[count].id = count;
 			xstats[count].value =
 				*(uint64_t *)(((char *)hw_stats) +
@@ -2314,7 +2311,6 @@ i40e_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 
 	for (i = 0; i < I40E_NB_TXQ_PRIO_XSTATS; i++) {
 		for (prio = 0; prio < 8; prio++) {
-			xstats[count].name[0] = '\0';
 			xstats[count].id = count;
 			xstats[count].value =
 				*(uint64_t *)(((char *)hw_stats) +
diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
index c3301c5..ad6238d 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -1022,7 +1022,6 @@ static int i40evf_dev_xstats_get(struct rte_eth_dev *dev,
 
 	/* loop over xstats array and values from pstats */
 	for (i = 0; i < I40EVF_NB_XSTATS; i++) {
-		xstats[i].name[0] = '\0';
 		xstats[i].id = i;
 		xstats[i].value = *(uint64_t *)(((char *)pstats) +
 			rte_i40evf_stats_strings[i].offset);
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index bb5940b..4c121ba 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -2808,7 +2808,6 @@ ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 	count = 0;
 	for (i = 0; i < IXGBE_NB_HW_STATS; i++) {
 		xstats[count].id = count;
-		xstats[count].name[0] = '\0';
 		xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
 				rte_ixgbe_stats_strings[i].offset);
 		count++;
@@ -2818,7 +2817,6 @@ ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 	for (stat = 0; stat < IXGBE_NB_RXQ_PRIO_STATS; stat++) {
 		for (i = 0; i < IXGBE_NB_RXQ_PRIO_VALUES; i++) {
 			xstats[count].id = count;
-			xstats[count].name[0] = '\0';
 			xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
 					rte_ixgbe_rxq_strings[stat].offset +
 					(sizeof(uint64_t) * i));
@@ -2830,7 +2828,6 @@ ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 	for (stat = 0; stat < IXGBE_NB_TXQ_PRIO_STATS; stat++) {
 		for (i = 0; i < IXGBE_NB_TXQ_PRIO_VALUES; i++) {
 			xstats[count].id = count;
-			xstats[count].name[0] = '\0';
 			xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
 					rte_ixgbe_txq_strings[stat].offset +
 					(sizeof(uint64_t) * i));
diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c
index 9d549de..bfd3748 100644
--- a/drivers/net/virtio/virtio_ethdev.c
+++ b/drivers/net/virtio/virtio_ethdev.c
@@ -780,7 +780,6 @@ virtio_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 		unsigned t;
 
 		for (t = 0; t < VIRTIO_NB_Q_XSTATS; t++) {
-			xstats[count].name[0] = '\0';
 			xstats[count].id = count;
 			xstats[count].value = *(uint64_t *)(((char *)rxvq) +
 				rte_virtio_q_stat_strings[t].offset);
@@ -797,7 +796,6 @@ virtio_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 		unsigned t;
 
 		for (t = 0; t < VIRTIO_NB_Q_XSTATS; t++) {
-			xstats[count].name[0] = '\0';
 			xstats[count].id = count;
 			xstats[count].value = *(uint64_t *)(((char *)txvq) +
 				rte_virtio_q_stat_strings[t].offset);
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 86fb0bc..0a533e6 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -1627,7 +1627,6 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
 		stats_ptr = RTE_PTR_ADD(&eth_stats,
 					rte_stats_strings[i].offset);
 		val = *stats_ptr;
-		xstats[count].name[0] = '\0';
 		xstats[count].id = count + xcount;
 		xstats[count++].value = val;
 	}
@@ -1639,7 +1638,6 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
 					rte_rxq_stats_strings[i].offset +
 					q * sizeof(uint64_t));
 			val = *stats_ptr;
-			xstats[count].name[0] = '\0';
 			xstats[count].id = count + xcount;
 			xstats[count++].value = val;
 		}
@@ -1652,7 +1650,6 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
 					rte_txq_stats_strings[i].offset +
 					q * sizeof(uint64_t));
 			val = *stats_ptr;
-			xstats[count].name[0] = '\0';
 			xstats[count].id = count + xcount;
 			xstats[count++].value = val;
 		}
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index d663d60..a82794d 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -915,8 +915,6 @@ struct rte_eth_txq_info {
  * structure.
  */
 struct rte_eth_xstats {
-	/* FIXME: Remove name[] once remaining drivers converted */
-	char name[RTE_ETH_XSTATS_NAME_SIZE];
 	uint64_t id;
 	uint64_t value;
 };
-- 
2.5.5

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

* [PATCH v3 10/10] doc: update xstats documentation
  2016-05-30 10:48   ` [PATCH v3 00/10] " Remy Horton
                       ` (8 preceding siblings ...)
  2016-05-30 10:48     ` [PATCH v3 09/10] remove name field from struct rte_eth_xstats Remy Horton
@ 2016-05-30 10:48     ` Remy Horton
  2016-06-09  8:48       ` Mcnamara, John
  2016-06-06 12:45     ` [PATCH v3 00/10] Remove string operations from xstats David Harton (dharton)
  2016-06-13 15:51     ` [PATCH v4 0/8] " Remy Horton
  11 siblings, 1 reply; 71+ messages in thread
From: Remy Horton @ 2016-05-30 10:48 UTC (permalink / raw)
  To: dev

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 doc/guides/prog_guide/poll_mode_drv.rst | 25 +++++++++++++++++++++----
 1 file changed, 21 insertions(+), 4 deletions(-)

diff --git a/doc/guides/prog_guide/poll_mode_drv.rst b/doc/guides/prog_guide/poll_mode_drv.rst
index 7698692..6cd86dd 100644
--- a/doc/guides/prog_guide/poll_mode_drv.rst
+++ b/doc/guides/prog_guide/poll_mode_drv.rst
@@ -299,10 +299,27 @@ Extended Statistics API
 ~~~~~~~~~~~~~~~~~~~~~~~
 
 The extended statistics API allows each individual PMD to expose a unique set
-of statistics. The client of the API provides an array of
-``struct rte_eth_xstats`` type. Each ``struct rte_eth_xstats`` contains a
-string and value pair. The amount of xstats exposed, and position of the
-statistic in the array must remain constant during runtime.
+of statistics. Accessing these from application programs is done via three
+functions:
+
+* ``rte_eth_xstats_count``: Fetches the number of extended statistics.
+* ``rte_eth_xstats_get``: Fills in an array of ``struct rte_eth_xstats``
+  with extended statistics.
+* ``rte_eth_xstats_names``: Fills in an array of ``struct rte_eth_name``
+  with extended statistic name lookup information.
+
+Each ``struct rte_eth_xstats`` contains an identifier and value pair, and
+each ``struct rte_eth_xstats_name`` contains an identifier and string pair.
+Each identifier within ``struct rte_eth_xstats`` must have a corresponding
+entry in ``struct rte_eth_xstats_name`` with a matching identifier. These
+identifiers, as well as the number of extended statistic exposed, must
+remain constant during runtime.
+
+Note that extended statistic identifiers are driver-specific, and hence
+might not be the same for different ports. Although it is expected that
+drivers will make the identifiers used within ``struct rte_eth_xstats`` and
+``struct rte_eth_xstats_name`` entries match the entries' array index, this
+property should not be relied on by applications for lookups.
 
 A naming scheme exists for the strings exposed to clients of the API. This is
 to allow scraping of the API for statistics of interest. The naming scheme uses
-- 
2.5.5

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

* Re: [PATCH v3 00/10] Remove string operations from xstats
  2016-05-30 10:48   ` [PATCH v3 00/10] " Remy Horton
                       ` (9 preceding siblings ...)
  2016-05-30 10:48     ` [PATCH v3 10/10] doc: update xstats documentation Remy Horton
@ 2016-06-06 12:45     ` David Harton (dharton)
  2016-06-13 15:51     ` [PATCH v4 0/8] " Remy Horton
  11 siblings, 0 replies; 71+ messages in thread
From: David Harton (dharton) @ 2016-06-06 12:45 UTC (permalink / raw)
  To: Remy Horton, dev, Thomas Monjalon, Helin Zhang, Wenzhuo Lu,
	Jing Chen, Huawei Xie

Acked-by: David Harton <dharton@cisco.com>

> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Remy Horton
> Sent: Monday, May 30, 2016 6:48 AM
> To: dev@dpdk.org; Thomas Monjalon <thomas.monjalon@6wind.com>; Helin Zhang
> <helin.zhang@intel.com>; Wenzhuo Lu <wenzhuo.lu@intel.com>; Jing Chen
> <jing.d.chen@intel.com>; Huawei Xie <huawei.xie@intel.com>
> Subject: [dpdk-dev] [PATCH v3 00/10] Remove string operations from xstats
> 
> The current extended ethernet statistics fetching involve doing several
> string operations, which causes performance issues if there are lots of
> statistics and/or network interfaces. This patchset changes the API for
> xstats to use integer identifiers instead of strings and implements
> this new API for the ixgbe, i40e, e1000, fm10k, and virtio drivers.
> 
> --
> 
> v3 changes:
> * Corrected ixgbe vf xstats fetching
> * Added xstats changes to e1000, f10k, and virtio drivers
> * Added cleanup patch that removes now-redundant name field
> * Removed ethtool xstats command
> * Removed unused .xstats_count from eth-dev_ops
> * Changed test-pmd & proc_info to use new API
> * Added documentation update
> * Added missing changes to .map file (affected shared lib builds)
> 
> v2 changes:
> * Fetching xstats count now seperate API function
> * Added #define constants for some magic numbers
> * Fixed bug with virtual function count fetching
> * For non-xstats-supporting drivers, queue stats returned
> * Some refactoring/cleanups
> * Removed index assumption from example
> 
> Remy Horton (10):
>   rte: change xstats to use integer ids
>   drivers/net/ixgbe: change xstats to use integer ids
>   drivers/net/e1000: change xstats to use integer ids
>   drivers/net/fm10k: change xstats to use integer ids
>   drivers/net/i40e: change xstats to use integer ids
>   drivers/net/virtio: change xstats to use integer ids
>   app/test-pmd: change xstats to use integer ids
>   app/proc_info: change xstats to use integer ids
>   remove name field from struct rte_eth_xstats
>   doc: update xstats documentation
> 
>  app/proc_info/main.c                    | 26 ++++++++-
>  app/test-pmd/config.c                   | 52 +++++++++++++----
>  doc/guides/prog_guide/poll_mode_drv.rst | 25 +++++++--
>  drivers/net/e1000/igb_ethdev.c          | 50 +++++++++++++++--
>  drivers/net/fm10k/fm10k_ethdev.c        | 52 ++++++++++++++---
>  drivers/net/i40e/i40e_ethdev.c          | 77 +++++++++++++++++++++-----
>  drivers/net/i40e/i40e_ethdev_vf.c       | 24 +++++++-
>  drivers/net/ixgbe/ixgbe_ethdev.c        | 98
> ++++++++++++++++++++++++++++-----
>  drivers/net/virtio/virtio_ethdev.c      | 60 +++++++++++++++++---
>  lib/librte_ether/rte_ethdev.c           | 92
> ++++++++++++++++++++++++++++---
>  lib/librte_ether/rte_ethdev.h           | 44 ++++++++++++++-
>  lib/librte_ether/rte_ether_version.map  |  7 +++
>  12 files changed, 527 insertions(+), 80 deletions(-)
> 
> --
> 2.5.5

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

* Re: [PATCH v3 01/10] rte: change xstats to use integer ids
  2016-05-30 10:48     ` [PATCH v3 01/10] rte: change xstats to use integer ids Remy Horton
@ 2016-06-08  9:37       ` Thomas Monjalon
  2016-06-08 11:16         ` Remy Horton
  0 siblings, 1 reply; 71+ messages in thread
From: Thomas Monjalon @ 2016-06-08  9:37 UTC (permalink / raw)
  To: Remy Horton; +Cc: dev

2016-05-30 11:48, Remy Horton:
>  struct rte_eth_xstats {
> +	/* FIXME: Remove name[] once remaining drivers converted */
>  	char name[RTE_ETH_XSTATS_NAME_SIZE];

What is the plan? This field must be deprecated with an attribute.
We cannot have 2 different APIs depending of the driver.
What are the remaining drivers to convert?

> +	uint64_t id;
>  	uint64_t value;
>  };
>  
> +/**
> + * A name-key lookup element for extended statistics.
> + *
> + * This structure is used to map between names and ID numbers
> + * for extended ethernet statistics.
> + */
> +struct rte_eth_xstats_name {
> +	char name[RTE_ETH_XSTATS_NAME_SIZE];
> +	uint64_t id;
> +};

This structure and the other one (rte_eth_xstats) are badly named.
There is only one stat in each. So they should not have the plural form.
rte_eth_xstat and rte_eth_xstat_name would be better.

[...]
>  /**
> + * Retrieve names of extended statistics of an Ethernet device.
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param ptr_names
> + *  Block of memory to insert names into. Must be at least limit in size.

"xstat_names" would be a better name than "ptr_names".
We don't use ptr in the variable names because it doesn't really convey a
semantic information.

> + * @param limit
> + *  Capacity of ptr_strings (number of names).

We are more used to "size" than "limit".

> + * @return
> + *  If successful, number of statistics; negative on error.
> + */
> +int rte_eth_xstats_names(uint8_t port_id, struct rte_eth_xstats_name *ptr_names,

Why not rte_eth_xstats_get_names?

> +	unsigned limit);

A (double) indent tab is missing.

> +
> +/**
> + * Retrieve number of extended statistics of an Ethernet device.
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @return
> + *  If successful, number of statistics; negative on error.
> + */
> +int rte_eth_xstats_count(uint8_t port_id);

This function is useless because we can have the count with
rte_eth_xstats_get(p, NULL, 0)
By the way it would be more consistent to have the same behaviour
in rte_eth_xstats_names().

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

* Re: [PATCH v3 01/10] rte: change xstats to use integer ids
  2016-06-08  9:37       ` Thomas Monjalon
@ 2016-06-08 11:16         ` Remy Horton
  2016-06-08 12:22           ` Thomas Monjalon
  0 siblings, 1 reply; 71+ messages in thread
From: Remy Horton @ 2016-06-08 11:16 UTC (permalink / raw)
  To: Thomas Monjalon; +Cc: dev

'noon,

On 08/06/2016 10:37, Thomas Monjalon wrote:
> 2016-05-30 11:48, Remy Horton:
>>   struct rte_eth_xstats {
>> +	/* FIXME: Remove name[] once remaining drivers converted */
>>   	char name[RTE_ETH_XSTATS_NAME_SIZE];
>
> What is the plan? This field must be deprecated with an attribute.
> We cannot have 2 different APIs depending of the driver.

This is where it gets logistically tricky..

Since there's an API/ABI breakage notice in place on this, my own 
preference would be to have the entire patchset quashed into a single 
patch. Problem is that rte/app changes (patches 1 & 7-9) are normally 
applied via master whereas driver changes (patches 2-6) go in via 
dpdk-next-net - it is not clear to me how patches should be submitted 
for this case..


> What are the remaining drivers to convert?

Opps, none. All relevant drivers are converted..


> This structure and the other one (rte_eth_xstats) are badly named.
> There is only one stat in each. So they should not have the plural form.
> rte_eth_xstat and rte_eth_xstat_name would be better.

I kept rte_eth_xstats as it was the name already in use within DPDK. 
Will change the other.


>> +int rte_eth_xstats_count(uint8_t port_id);
>
> This function is useless because we can have the count with
> rte_eth_xstats_get(p, NULL, 0)
> By the way it would be more consistent to have the same behaviour
> in rte_eth_xstats_names().

Feedback I got with earlier patches was that a seperate count function 
was preferable to overloading the fetch function using *data==NULL - is 
the use of the latter specifically preferred?

Other comments noted.

..Remy

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

* Re: [PATCH v3 01/10] rte: change xstats to use integer ids
  2016-06-08 11:16         ` Remy Horton
@ 2016-06-08 12:22           ` Thomas Monjalon
  0 siblings, 0 replies; 71+ messages in thread
From: Thomas Monjalon @ 2016-06-08 12:22 UTC (permalink / raw)
  To: Remy Horton; +Cc: dev

2016-06-08 12:16, Remy Horton:
> 'noon,
> 
> On 08/06/2016 10:37, Thomas Monjalon wrote:
> > 2016-05-30 11:48, Remy Horton:
> >>   struct rte_eth_xstats {
> >> +	/* FIXME: Remove name[] once remaining drivers converted */
> >>   	char name[RTE_ETH_XSTATS_NAME_SIZE];
> >
> > What is the plan? This field must be deprecated with an attribute.
> > We cannot have 2 different APIs depending of the driver.
> 
> This is where it gets logistically tricky..
> 
> Since there's an API/ABI breakage notice in place on this, my own 
> preference would be to have the entire patchset quashed into a single 
> patch. Problem is that rte/app changes (patches 1 & 7-9) are normally 
> applied via master whereas driver changes (patches 2-6) go in via 
> dpdk-next-net - it is not clear to me how patches should be submitted 
> for this case..

Misunderstanding here. Patches are fine and will be integrated in the
main tree because they are not only some drivers changes.
I was talking about the old API with name in rte_eth_xstats.
I have not seen the patch 9 which removes it.

> >> +int rte_eth_xstats_count(uint8_t port_id);
> >
> > This function is useless because we can have the count with
> > rte_eth_xstats_get(p, NULL, 0)
> > By the way it would be more consistent to have the same behaviour
> > in rte_eth_xstats_names().
> 
> Feedback I got with earlier patches was that a seperate count function 
> was preferable to overloading the fetch function using *data==NULL - is 
> the use of the latter specifically preferred?

I prefer the fetch/NULL style to get a count.
It also handles nicely the fetch error because of a too small buffer.

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

* Re: [PATCH v3 09/10] remove name field from struct rte_eth_xstats
  2016-05-30 10:48     ` [PATCH v3 09/10] remove name field from struct rte_eth_xstats Remy Horton
@ 2016-06-08 12:23       ` Thomas Monjalon
  0 siblings, 0 replies; 71+ messages in thread
From: Thomas Monjalon @ 2016-06-08 12:23 UTC (permalink / raw)
  To: Remy Horton; +Cc: dev, Helin Zhang, Wenzhuo Lu, Jing Chen, Huawei Xie

2016-05-30 11:48, Remy Horton:
>  struct rte_eth_xstats {
> -	/* FIXME: Remove name[] once remaining drivers converted */
> -	char name[RTE_ETH_XSTATS_NAME_SIZE];
>  	uint64_t id;
>  	uint64_t value;
>  };

While changing the content of this struct, it can be the opportunity
to fix its name from rte_eth_xstats to rte_eth_xstat.

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

* Re: [PATCH v3 10/10] doc: update xstats documentation
  2016-05-30 10:48     ` [PATCH v3 10/10] doc: update xstats documentation Remy Horton
@ 2016-06-09  8:48       ` Mcnamara, John
  0 siblings, 0 replies; 71+ messages in thread
From: Mcnamara, John @ 2016-06-09  8:48 UTC (permalink / raw)
  To: Horton, Remy, dev

> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Remy Horton
> Sent: Monday, May 30, 2016 11:48 AM
> To: dev@dpdk.org
> Subject: [dpdk-dev] [PATCH v3 10/10] doc: update xstats documentation
> 
> Signed-off-by: Remy Horton <remy.horton@intel.com>

Good clear update.

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

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

* [PATCH v4 0/8] Remove string operations from xstats
  2016-05-30 10:48   ` [PATCH v3 00/10] " Remy Horton
                       ` (10 preceding siblings ...)
  2016-06-06 12:45     ` [PATCH v3 00/10] Remove string operations from xstats David Harton (dharton)
@ 2016-06-13 15:51     ` Remy Horton
  2016-06-13 15:51       ` [PATCH v4 1/8] rte: change xstats to use integer ids Remy Horton
                         ` (8 more replies)
  11 siblings, 9 replies; 71+ messages in thread
From: Remy Horton @ 2016-06-13 15:51 UTC (permalink / raw)
  To: dev, Thomas Monjalon, Helin Zhang, Wenzhuo Lu, Jing Chen,
	Huawei Xie, John McNamara

The current extended ethernet statistics fetching involve doing several
string operations, which causes performance issues if there are lots of
statistics and/or network interfaces. This patchset changes the API for
xstats to use integer identifiers instead of strings and implements
this new API for the ixgbe, i40e, e1000, fm10k, and virtio drivers.

--

v4 changes:
* rte_eth_xstats_count() removed
* rte_eth_xstats_names() changed to rte_eth_xstats_get_names()
* struct rte_eth_xstats_name renamed to rte_eth_xstat_name
* struct rte_eth_xstats renamed to rte_eth_xstat
* struct rte_eth_dev: .xstats_names renamed to .xstats_get_names
* Other minor local variable name changes
* Documentation updates due to renames
* API changeover patches squashed

v3 changes:
* Corrected ixgbe vf xstats fetching
* Added xstats changes to e1000, f10k, and virtio drivers
* Added cleanup patch that removes now-redundant name field
* Removed ethtool xstats command 
* Removed unused .xstats_count from eth-dev_ops
* Changed test-pmd & proc_info to use new API
* Added documentation update
* Added missing changes to .map file (affected shared lib builds)

v2 changes:
* Fetching xstats count now seperate API function
* Added #define constants for some magic numbers
* Fixed bug with virtual function count fetching
* For non-xstats-supporting drivers, queue stats returned
* Some refactoring/cleanups
* Removed index assumption from example

Remy Horton (8):
  rte: change xstats to use integer ids
  drivers/net/ixgbe: change xstats to use integer ids
  drivers/net/e1000: change xstats to use integer ids
  drivers/net/fm10k: change xstats to use integer ids
  drivers/net/i40e: change xstats to use integer ids
  drivers/net/virtio: change xstats to use integer ids
  rte: change xstats usage to new API
  doc: update xstats documentation

 app/proc_info/main.c                    |  29 +++++++--
 app/test-pmd/config.c                   |  54 ++++++++++++----
 doc/guides/prog_guide/poll_mode_drv.rst |  25 ++++++--
 drivers/net/e1000/igb_ethdev.c          |  58 ++++++++++++++---
 drivers/net/fm10k/fm10k_ethdev.c        |  54 +++++++++++++---
 drivers/net/i40e/i40e_ethdev.c          |  82 +++++++++++++++++++-----
 drivers/net/i40e/i40e_ethdev_vf.c       |  29 +++++++--
 drivers/net/ixgbe/ixgbe_ethdev.c        | 106 ++++++++++++++++++++++++++------
 drivers/net/virtio/virtio_ethdev.c      |  64 ++++++++++++++++---
 lib/librte_ether/rte_ethdev.c           |  93 +++++++++++++++++++++++++---
 lib/librte_ether/rte_ethdev.h           |  42 +++++++++++--
 lib/librte_ether/rte_ether_version.map  |   7 +++
 12 files changed, 542 insertions(+), 101 deletions(-)

-- 
2.5.5

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

* [PATCH v4 1/8] rte: change xstats to use integer ids
  2016-06-13 15:51     ` [PATCH v4 0/8] " Remy Horton
@ 2016-06-13 15:51       ` Remy Horton
  2016-06-15  9:19         ` Thomas Monjalon
  2016-06-13 15:51       ` [PATCH v4 2/8] drivers/net/ixgbe: " Remy Horton
                         ` (7 subsequent siblings)
  8 siblings, 1 reply; 71+ messages in thread
From: Remy Horton @ 2016-06-13 15:51 UTC (permalink / raw)
  To: dev, Thomas Monjalon

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 lib/librte_ether/rte_ethdev.c          | 94 +++++++++++++++++++++++++++++++---
 lib/librte_ether/rte_ethdev.h          | 35 +++++++++++++
 lib/librte_ether/rte_ether_version.map |  7 +++
 3 files changed, 128 insertions(+), 8 deletions(-)

diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index e148028..79a01cc 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -1502,6 +1502,86 @@ rte_eth_stats_reset(uint8_t port_id)
 	dev->data->rx_mbuf_alloc_failed = 0;
 }
 
+static int
+get_xstats_count(uint8_t port_id)
+{
+	struct rte_eth_dev *dev;
+	int count;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL);
+	dev = &rte_eth_devices[port_id];
+	if (dev->dev_ops->xstats_get_names != NULL) {
+		count = (*dev->dev_ops->xstats_get_names)(dev, NULL, 0);
+		if (count < 0)
+			return count;
+	} else
+		count = 0;
+	count += RTE_NB_STATS;
+	count += dev->data->nb_rx_queues * RTE_NB_RXQ_STATS;
+	count += dev->data->nb_tx_queues * RTE_NB_TXQ_STATS;
+	return count;
+}
+
+int
+rte_eth_xstats_get_names(uint8_t port_id,
+	struct rte_eth_xstat_name *xstats_names,
+	unsigned size)
+{
+	struct rte_eth_dev *dev;
+	int cnt_used_entries;
+	int cnt_expected_entries;
+	uint32_t idx, id_queue;
+
+	cnt_expected_entries = get_xstats_count(port_id);
+	if (xstats_names == NULL || cnt_expected_entries < 0)
+		return cnt_expected_entries;
+	if ((int)size < cnt_expected_entries)
+		return -ERANGE;
+
+	/* port_id checked in get_xstats_count() */
+	dev = &rte_eth_devices[port_id];
+	if (dev->dev_ops->xstats_get_names != NULL) {
+		cnt_used_entries = (*dev->dev_ops->xstats_get_names)(
+			dev, xstats_names, size);
+		if (cnt_used_entries < 0)
+			return cnt_used_entries;
+	} else
+		/* Driver itself does not support extended stats, but
+		 * still have basic stats.
+		 */
+		cnt_used_entries = 0;
+
+	for (idx = 0; idx < RTE_NB_STATS; idx++) {
+		xstats_names[cnt_used_entries].id = cnt_used_entries;
+		snprintf(xstats_names[cnt_used_entries].name,
+			sizeof(xstats_names[0].name),
+			"%s", rte_stats_strings[idx].name);
+		cnt_used_entries++;
+	}
+	for (id_queue = 0; id_queue < dev->data->nb_rx_queues; id_queue++) {
+		for (idx = 0; idx < RTE_NB_RXQ_STATS; idx++) {
+			xstats_names[cnt_used_entries].id = cnt_used_entries;
+			snprintf(xstats_names[cnt_used_entries].name,
+				sizeof(xstats_names[0].name),
+				"rx_q%u%s",
+				id_queue, rte_rxq_stats_strings[idx].name);
+			cnt_used_entries++;
+		}
+
+	}
+	for (id_queue = 0; id_queue < dev->data->nb_tx_queues; id_queue++) {
+		for (idx = 0; idx < RTE_NB_TXQ_STATS; idx++) {
+			xstats_names[cnt_used_entries].id = cnt_used_entries;
+			snprintf(xstats_names[cnt_used_entries].name,
+				sizeof(xstats_names[0].name),
+				"tx_q%u%s",
+				id_queue, rte_txq_stats_strings[idx].name);
+			cnt_used_entries++;
+		}
+	}
+	return cnt_used_entries;
+}
+
 /* retrieve ethdev extended statistics */
 int
 rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
@@ -1546,8 +1626,8 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
 		stats_ptr = RTE_PTR_ADD(&eth_stats,
 					rte_stats_strings[i].offset);
 		val = *stats_ptr;
-		snprintf(xstats[count].name, sizeof(xstats[count].name),
-			"%s", rte_stats_strings[i].name);
+		xstats[count].name[0] = '\0';
+		xstats[count].id = count + xcount;
 		xstats[count++].value = val;
 	}
 
@@ -1558,9 +1638,8 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
 					rte_rxq_stats_strings[i].offset +
 					q * sizeof(uint64_t));
 			val = *stats_ptr;
-			snprintf(xstats[count].name, sizeof(xstats[count].name),
-				"rx_q%u_%s", q,
-				rte_rxq_stats_strings[i].name);
+			xstats[count].name[0] = '\0';
+			xstats[count].id = count + xcount;
 			xstats[count++].value = val;
 		}
 	}
@@ -1572,9 +1651,8 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
 					rte_txq_stats_strings[i].offset +
 					q * sizeof(uint64_t));
 			val = *stats_ptr;
-			snprintf(xstats[count].name, sizeof(xstats[count].name),
-				"tx_q%u_%s", q,
-				rte_txq_stats_strings[i].name);
+			xstats[count].name[0] = '\0';
+			xstats[count].id = count + xcount;
 			xstats[count++].value = val;
 		}
 	}
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 2757510..7d8ce3c 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -916,9 +916,21 @@ struct rte_eth_txq_info {
  */
 struct rte_eth_xstats {
 	char name[RTE_ETH_XSTATS_NAME_SIZE];
+	uint64_t id;
 	uint64_t value;
 };
 
+/**
+ * A name-key lookup element for extended statistics.
+ *
+ * This structure is used to map between names and ID numbers
+ * for extended ethernet statistics.
+ */
+struct rte_eth_xstat_name {
+	char name[RTE_ETH_XSTATS_NAME_SIZE];
+	uint64_t id;
+};
+
 #define ETH_DCB_NUM_TCS    8
 #define ETH_MAX_VMDQ_POOL  64
 
@@ -1054,6 +1066,10 @@ typedef int (*eth_xstats_get_t)(struct rte_eth_dev *dev,
 typedef void (*eth_xstats_reset_t)(struct rte_eth_dev *dev);
 /**< @internal Reset extended stats of an Ethernet device. */
 
+typedef int (*eth_xstats_get_names_t)(struct rte_eth_dev *dev,
+	struct rte_eth_xstat_name *xstats_names, unsigned size);
+/**< @internal Get names of extended stats of an Ethernet device. */
+
 typedef int (*eth_queue_stats_mapping_set_t)(struct rte_eth_dev *dev,
 					     uint16_t queue_id,
 					     uint8_t stat_idx,
@@ -1401,6 +1417,8 @@ struct eth_dev_ops {
 	eth_stats_reset_t          stats_reset;   /**< Reset generic device statistics. */
 	eth_xstats_get_t           xstats_get;    /**< Get extended device statistics. */
 	eth_xstats_reset_t         xstats_reset;  /**< Reset extended device statistics. */
+	eth_xstats_get_names_t     xstats_get_names;
+	/**< Get names of extended statistics. */
 	eth_queue_stats_mapping_set_t queue_stats_mapping_set;
 	/**< Configure per queue stat counter mapping. */
 	eth_dev_infos_get_t        dev_infos_get; /**< Get device info. */
@@ -2253,6 +2271,23 @@ int rte_eth_stats_get(uint8_t port_id, struct rte_eth_stats *stats);
 void rte_eth_stats_reset(uint8_t port_id);
 
 /**
+ * Retrieve names of extended statistics of an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param xstats_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 xstats_names (number of names).
+ * @return
+ *  If successful, number of statistics; negative on error.
+ */
+int rte_eth_xstats_get_names(uint8_t port_id,
+		struct rte_eth_xstat_name *xstats_names,
+		unsigned size);
+
+/**
  * Retrieve 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 214ecc7..bb339e1 100644
--- a/lib/librte_ether/rte_ether_version.map
+++ b/lib/librte_ether/rte_ether_version.map
@@ -132,3 +132,10 @@ DPDK_16.04 {
 	rte_eth_tx_buffer_set_err_callback;
 
 } DPDK_2.2;
+
+DPDK_16.07 {
+	global:
+
+	rte_eth_xstats_names;
+	rte_eth_xstats_count;
+} DPDK_16.04;
-- 
2.5.5

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

* [PATCH v4 2/8] drivers/net/ixgbe: change xstats to use integer ids
  2016-06-13 15:51     ` [PATCH v4 0/8] " Remy Horton
  2016-06-13 15:51       ` [PATCH v4 1/8] rte: change xstats to use integer ids Remy Horton
@ 2016-06-13 15:51       ` Remy Horton
  2016-06-13 15:51       ` [PATCH v4 3/8] drivers/net/e1000: " Remy Horton
                         ` (6 subsequent siblings)
  8 siblings, 0 replies; 71+ messages in thread
From: Remy Horton @ 2016-06-13 15:51 UTC (permalink / raw)
  To: dev, Helin Zhang, Thomas Monjalon

The current extended ethernet statistics fetching involve doing several
string operations, which causes performance issues if there are lots of
statistics and/or network interfaces. This patch changes the ixgbe driver
to use the new API that seperates name string and value queries.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 drivers/net/ixgbe/ixgbe_ethdev.c | 101 +++++++++++++++++++++++++++++++++------
 1 file changed, 86 insertions(+), 15 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index a2b170b..9e73492 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -179,6 +179,10 @@ static int ixgbevf_dev_xstats_get(struct rte_eth_dev *dev,
 				  struct rte_eth_xstats *xstats, unsigned n);
 static void ixgbe_dev_stats_reset(struct rte_eth_dev *dev);
 static void ixgbe_dev_xstats_reset(struct rte_eth_dev *dev);
+static int ixgbe_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
+	struct rte_eth_xstat_name *xstats_names, __rte_unused unsigned limit);
+static int ixgbevf_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
+	struct rte_eth_xstat_name *xstats_names, __rte_unused unsigned limit);
 static int ixgbe_dev_queue_stats_mapping_set(struct rte_eth_dev *eth_dev,
 					     uint16_t queue_id,
 					     uint8_t stat_idx,
@@ -466,6 +470,7 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = {
 	.xstats_get           = ixgbe_dev_xstats_get,
 	.stats_reset          = ixgbe_dev_stats_reset,
 	.xstats_reset         = ixgbe_dev_xstats_reset,
+	.xstats_get_names     = ixgbe_dev_xstats_get_names,
 	.queue_stats_mapping_set = ixgbe_dev_queue_stats_mapping_set,
 	.dev_infos_get        = ixgbe_dev_info_get,
 	.dev_supported_ptypes_get = ixgbe_dev_supported_ptypes_get,
@@ -555,6 +560,7 @@ static const struct eth_dev_ops ixgbevf_eth_dev_ops = {
 	.xstats_get           = ixgbevf_dev_xstats_get,
 	.stats_reset          = ixgbevf_dev_stats_reset,
 	.xstats_reset         = ixgbevf_dev_stats_reset,
+	.xstats_get_names     = ixgbevf_dev_xstats_get_names,
 	.dev_close            = ixgbevf_dev_close,
 	.allmulticast_enable  = ixgbevf_dev_allmulticast_enable,
 	.allmulticast_disable = ixgbevf_dev_allmulticast_disable,
@@ -685,6 +691,7 @@ static const struct rte_ixgbe_xstats_name_off rte_ixgbe_rxq_strings[] = {
 
 #define IXGBE_NB_RXQ_PRIO_STATS (sizeof(rte_ixgbe_rxq_strings) / \
 			   sizeof(rte_ixgbe_rxq_strings[0]))
+#define IXGBE_NB_RXQ_PRIO_VALUES 8
 
 static const struct rte_ixgbe_xstats_name_off rte_ixgbe_txq_strings[] = {
 	{"xon_packets", offsetof(struct ixgbe_hw_stats, pxontxc)},
@@ -695,6 +702,7 @@ static const struct rte_ixgbe_xstats_name_off rte_ixgbe_txq_strings[] = {
 
 #define IXGBE_NB_TXQ_PRIO_STATS (sizeof(rte_ixgbe_txq_strings) / \
 			   sizeof(rte_ixgbe_txq_strings[0]))
+#define IXGBE_NB_TXQ_PRIO_VALUES 8
 
 static const struct rte_ixgbe_xstats_name_off rte_ixgbevf_stats_strings[] = {
 	{"rx_multicast_packets", offsetof(struct ixgbevf_hw_stats, vfmprc)},
@@ -2695,8 +2703,75 @@ ixgbe_dev_stats_reset(struct rte_eth_dev *dev)
 /* This function calculates the number of xstats based on the current config */
 static unsigned
 ixgbe_xstats_calc_num(void) {
-	return IXGBE_NB_HW_STATS + (IXGBE_NB_RXQ_PRIO_STATS * 8) +
-		(IXGBE_NB_TXQ_PRIO_STATS * 8);
+	return IXGBE_NB_HW_STATS +
+		(IXGBE_NB_RXQ_PRIO_STATS * IXGBE_NB_RXQ_PRIO_VALUES) +
+		(IXGBE_NB_TXQ_PRIO_STATS * IXGBE_NB_TXQ_PRIO_VALUES);
+}
+
+static int ixgbe_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
+	struct rte_eth_xstat_name *xstats_names, __rte_unused unsigned limit)
+{
+	const unsigned cnt_stats = ixgbe_xstats_calc_num();
+	unsigned stat, i, count;
+
+	if (xstats_names != NULL) {
+		count = 0;
+
+		/* Note: limit >= cnt_stats checked upstream
+		 * in rte_eth_xstats_names()
+		 */
+
+		/* Extended stats from ixgbe_hw_stats */
+		for (i = 0; i < IXGBE_NB_HW_STATS; i++) {
+			xstats_names[count].id = count;
+			snprintf(xstats_names[count].name,
+				sizeof(xstats_names[count].name),
+				"%s",
+				rte_ixgbe_stats_strings[i].name);
+			count++;
+		}
+
+		/* RX Priority Stats */
+		for (stat = 0; stat < IXGBE_NB_RXQ_PRIO_STATS; stat++) {
+			for (i = 0; i < IXGBE_NB_RXQ_PRIO_VALUES; i++) {
+				xstats_names[count].id = count;
+				snprintf(xstats_names[count].name,
+					sizeof(xstats_names[count].name),
+					"rx_priority%u_%s", i,
+					rte_ixgbe_rxq_strings[stat].name);
+				count++;
+			}
+		}
+
+		/* TX Priority Stats */
+		for (stat = 0; stat < IXGBE_NB_TXQ_PRIO_STATS; stat++) {
+			for (i = 0; i < IXGBE_NB_TXQ_PRIO_VALUES; i++) {
+				xstats_names[count].id = count;
+				snprintf(xstats_names[count].name,
+					sizeof(xstats_names[count].name),
+					"tx_priority%u_%s", i,
+					rte_ixgbe_txq_strings[stat].name);
+				count++;
+			}
+		}
+	}
+	return cnt_stats;
+}
+
+static int ixgbevf_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
+	struct rte_eth_xstat_name *xstats_names, unsigned limit)
+{
+	unsigned i;
+
+	if (limit < IXGBEVF_NB_XSTATS && xstats_names != NULL)
+		return -ENOMEM;
+
+	if (xstats_names != NULL)
+		for (i = 0; i < IXGBEVF_NB_XSTATS; i++)
+			snprintf(xstats_names[i].name,
+				sizeof(xstats_names[i].name),
+				"%s", rte_ixgbevf_stats_strings[i].name);
+	return IXGBEVF_NB_XSTATS;
 }
 
 static int
@@ -2732,8 +2807,8 @@ ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 	/* Extended stats from ixgbe_hw_stats */
 	count = 0;
 	for (i = 0; i < IXGBE_NB_HW_STATS; i++) {
-		snprintf(xstats[count].name, sizeof(xstats[count].name), "%s",
-			 rte_ixgbe_stats_strings[i].name);
+		xstats[count].id = count;
+		xstats[count].name[0] = '\0';
 		xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
 				rte_ixgbe_stats_strings[i].offset);
 		count++;
@@ -2741,10 +2816,9 @@ ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 
 	/* RX Priority Stats */
 	for (stat = 0; stat < IXGBE_NB_RXQ_PRIO_STATS; stat++) {
-		for (i = 0; i < 8; i++) {
-			snprintf(xstats[count].name, sizeof(xstats[count].name),
-				 "rx_priority%u_%s", i,
-				 rte_ixgbe_rxq_strings[stat].name);
+		for (i = 0; i < IXGBE_NB_RXQ_PRIO_VALUES; i++) {
+			xstats[count].id = count;
+			xstats[count].name[0] = '\0';
 			xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
 					rte_ixgbe_rxq_strings[stat].offset +
 					(sizeof(uint64_t) * i));
@@ -2754,17 +2828,15 @@ ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 
 	/* TX Priority Stats */
 	for (stat = 0; stat < IXGBE_NB_TXQ_PRIO_STATS; stat++) {
-		for (i = 0; i < 8; i++) {
-			snprintf(xstats[count].name, sizeof(xstats[count].name),
-				 "tx_priority%u_%s", i,
-				 rte_ixgbe_txq_strings[stat].name);
+		for (i = 0; i < IXGBE_NB_TXQ_PRIO_VALUES; i++) {
+			xstats[count].id = count;
+			xstats[count].name[0] = '\0';
 			xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
 					rte_ixgbe_txq_strings[stat].offset +
 					(sizeof(uint64_t) * i));
 			count++;
 		}
 	}
-
 	return count;
 }
 
@@ -2829,8 +2901,7 @@ ixgbevf_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 
 	/* Extended stats */
 	for (i = 0; i < IXGBEVF_NB_XSTATS; i++) {
-		snprintf(xstats[i].name, sizeof(xstats[i].name),
-			 "%s", rte_ixgbevf_stats_strings[i].name);
+		xstats[i].id = i;
 		xstats[i].value = *(uint64_t *)(((char *)hw_stats) +
 			rte_ixgbevf_stats_strings[i].offset);
 	}
-- 
2.5.5

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

* [PATCH v4 3/8] drivers/net/e1000: change xstats to use integer ids
  2016-06-13 15:51     ` [PATCH v4 0/8] " Remy Horton
  2016-06-13 15:51       ` [PATCH v4 1/8] rte: change xstats to use integer ids Remy Horton
  2016-06-13 15:51       ` [PATCH v4 2/8] drivers/net/ixgbe: " Remy Horton
@ 2016-06-13 15:51       ` Remy Horton
  2016-06-13 15:51       ` [PATCH v4 4/8] drivers/net/fm10k: " Remy Horton
                         ` (5 subsequent siblings)
  8 siblings, 0 replies; 71+ messages in thread
From: Remy Horton @ 2016-06-13 15:51 UTC (permalink / raw)
  To: dev, Wenzhuo Lu, Thomas Monjalon

The current extended ethernet statistics fetching involve doing several
string operations, which causes performance issues if there are lots of
statistics and/or network interfaces. This patch changes the e1000 driver
to use the new API that seperates name string and value queries.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 drivers/net/e1000/igb_ethdev.c | 52 ++++++++++++++++++++++++++++++++++++++----
 1 file changed, 48 insertions(+), 4 deletions(-)

diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index f0921ee..dffa04f 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -100,6 +100,9 @@ static void eth_igb_stats_get(struct rte_eth_dev *dev,
 				struct rte_eth_stats *rte_stats);
 static int eth_igb_xstats_get(struct rte_eth_dev *dev,
 			      struct rte_eth_xstats *xstats, unsigned n);
+static int eth_igb_xstats_get_names(struct rte_eth_dev *dev,
+				    struct rte_eth_xstat_name *xstats_names,
+				    unsigned limit);
 static void eth_igb_stats_reset(struct rte_eth_dev *dev);
 static void eth_igb_xstats_reset(struct rte_eth_dev *dev);
 static void eth_igb_infos_get(struct rte_eth_dev *dev,
@@ -165,6 +168,9 @@ static void eth_igbvf_stats_get(struct rte_eth_dev *dev,
 				struct rte_eth_stats *rte_stats);
 static int eth_igbvf_xstats_get(struct rte_eth_dev *dev,
 				struct rte_eth_xstats *xstats, unsigned n);
+static int eth_igbvf_xstats_get_names(struct rte_eth_dev *dev,
+				      struct rte_eth_xstat_name *xstats_names,
+				      unsigned limit);
 static void eth_igbvf_stats_reset(struct rte_eth_dev *dev);
 static int igbvf_vlan_filter_set(struct rte_eth_dev *dev,
 		uint16_t vlan_id, int on);
@@ -324,6 +330,7 @@ static const struct eth_dev_ops eth_igb_ops = {
 	.link_update          = eth_igb_link_update,
 	.stats_get            = eth_igb_stats_get,
 	.xstats_get           = eth_igb_xstats_get,
+	.xstats_get_names     = eth_igb_xstats_get_names,
 	.stats_reset          = eth_igb_stats_reset,
 	.xstats_reset         = eth_igb_xstats_reset,
 	.dev_infos_get        = eth_igb_infos_get,
@@ -385,6 +392,7 @@ static const struct eth_dev_ops igbvf_eth_dev_ops = {
 	.link_update          = eth_igb_link_update,
 	.stats_get            = eth_igbvf_stats_get,
 	.xstats_get           = eth_igbvf_xstats_get,
+	.xstats_get_names     = eth_igbvf_xstats_get_names,
 	.stats_reset          = eth_igbvf_stats_reset,
 	.xstats_reset         = eth_igbvf_stats_reset,
 	.vlan_filter_set      = igbvf_vlan_filter_set,
@@ -1691,6 +1699,26 @@ eth_igb_xstats_reset(struct rte_eth_dev *dev)
 	memset(stats, 0, sizeof(*stats));
 }
 
+static int eth_igb_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
+	struct rte_eth_xstat_name *xstats_names,
+	__rte_unused unsigned limit)
+{
+	unsigned i;
+
+	if (xstats_names == NULL)
+		return IGB_NB_XSTATS;
+
+	/* Note: limit checked in rte_eth_xstats_names() */
+
+	for (i = 0; i < IGB_NB_XSTATS; i++) {
+		snprintf(xstats_names[i].name, sizeof(xstats_names[i].name),
+			 "%s", rte_igb_stats_strings[i].name);
+		xstats_names[i].id = i;
+	}
+
+	return IGB_NB_XSTATS;
+}
+
 static int
 eth_igb_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 		   unsigned n)
@@ -1713,8 +1741,8 @@ eth_igb_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 
 	/* Extended stats */
 	for (i = 0; i < IGB_NB_XSTATS; i++) {
-		snprintf(xstats[i].name, sizeof(xstats[i].name),
-			 "%s", rte_igb_stats_strings[i].name);
+		xstats[i].name[0] = '\0';
+		xstats[i].id = i;
 		xstats[i].value = *(uint64_t *)(((char *)hw_stats) +
 			rte_igb_stats_strings[i].offset);
 	}
@@ -1762,6 +1790,22 @@ igbvf_read_stats_registers(struct e1000_hw *hw, struct e1000_vf_stats *hw_stats)
 	    hw_stats->last_gotlbc, hw_stats->gotlbc);
 }
 
+static int eth_igbvf_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
+				     struct rte_eth_xstat_name *xstats_names,
+				     __rte_unused unsigned limit)
+{
+	unsigned i;
+
+	if (xstats_names != NULL)
+		for (i = 0; i < IGBVF_NB_XSTATS; i++) {
+			snprintf(xstats_names[i].name,
+				sizeof(xstats_names[i].name), "%s",
+				rte_igbvf_stats_strings[i].name);
+			xstats_names[i].id = i;
+		}
+	return IGBVF_NB_XSTATS;
+}
+
 static int
 eth_igbvf_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 		     unsigned n)
@@ -1780,8 +1824,8 @@ eth_igbvf_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 		return 0;
 
 	for (i = 0; i < IGBVF_NB_XSTATS; i++) {
-		snprintf(xstats[i].name, sizeof(xstats[i].name), "%s",
-			 rte_igbvf_stats_strings[i].name);
+		xstats[i].name[0] = '\0';
+		xstats[i].id = i;
 		xstats[i].value = *(uint64_t *)(((char *)hw_stats) +
 			rte_igbvf_stats_strings[i].offset);
 	}
-- 
2.5.5

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

* [PATCH v4 4/8] drivers/net/fm10k: change xstats to use integer ids
  2016-06-13 15:51     ` [PATCH v4 0/8] " Remy Horton
                         ` (2 preceding siblings ...)
  2016-06-13 15:51       ` [PATCH v4 3/8] drivers/net/e1000: " Remy Horton
@ 2016-06-13 15:51       ` Remy Horton
  2016-06-13 15:51       ` [PATCH v4 5/8] drivers/net/i40e: " Remy Horton
                         ` (4 subsequent siblings)
  8 siblings, 0 replies; 71+ messages in thread
From: Remy Horton @ 2016-06-13 15:51 UTC (permalink / raw)
  To: dev, Jing Chen, Thomas Monjalon

The current extended ethernet statistics fetching involve doing several
string operations, which causes performance issues if there are lots of
statistics and/or network interfaces. This patch changes the fm10k driver
to use the new API that seperates name string and value queries.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 drivers/net/fm10k/fm10k_ethdev.c | 55 +++++++++++++++++++++++++++++++++-------
 1 file changed, 46 insertions(+), 9 deletions(-)

diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c
index c2d377f..e07c1ec 100644
--- a/drivers/net/fm10k/fm10k_ethdev.c
+++ b/drivers/net/fm10k/fm10k_ethdev.c
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2013-2015 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2013-2016 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -1256,6 +1256,47 @@ fm10k_link_update(struct rte_eth_dev *dev,
 	return 0;
 }
 
+static int fm10k_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
+	struct rte_eth_xstat_name *xstats_names, __rte_unused unsigned limit)
+{
+	unsigned i, q;
+	unsigned count = 0;
+
+	if (xstats_names != NULL) {
+		/* Note: limit checked in rte_eth_xstats_names() */
+
+		/* Global stats */
+		for (i = 0; i < FM10K_NB_HW_XSTATS; i++) {
+			snprintf(xstats_names[count].name,
+				sizeof(xstats_names[count].name),
+				"%s", fm10k_hw_stats_strings[count].name);
+			xstats_names[count].id = count;
+			count++;
+		}
+
+		/* PF queue stats */
+		for (q = 0; q < FM10K_MAX_QUEUES_PF; q++) {
+			for (i = 0; i < FM10K_NB_RX_Q_XSTATS; i++) {
+				snprintf(xstats_names[count].name,
+					sizeof(xstats_names[count].name),
+					"rx_q%u_%s", q,
+					fm10k_hw_stats_rx_q_strings[i].name);
+				xstats_names[count].id = count;
+				count++;
+			}
+			for (i = 0; i < FM10K_NB_TX_Q_XSTATS; i++) {
+				snprintf(xstats_names[count].name,
+					sizeof(xstats_names[count].name),
+					"tx_q%u_%s", q,
+					fm10k_hw_stats_tx_q_strings[i].name);
+				xstats_names[count].id = count;
+				count++;
+			}
+		}
+	}
+	return FM10K_NB_XSTATS;
+}
+
 static int
 fm10k_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 		 unsigned n)
@@ -1269,8 +1310,7 @@ fm10k_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 
 	/* Global stats */
 	for (i = 0; i < FM10K_NB_HW_XSTATS; i++) {
-		snprintf(xstats[count].name, sizeof(xstats[count].name),
-			 "%s", fm10k_hw_stats_strings[count].name);
+		xstats[count].name[0] = '\0';
 		xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
 			fm10k_hw_stats_strings[count].offset);
 		count++;
@@ -1279,18 +1319,14 @@ fm10k_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 	/* PF queue stats */
 	for (q = 0; q < FM10K_MAX_QUEUES_PF; q++) {
 		for (i = 0; i < FM10K_NB_RX_Q_XSTATS; i++) {
-			snprintf(xstats[count].name, sizeof(xstats[count].name),
-				 "rx_q%u_%s", q,
-				 fm10k_hw_stats_rx_q_strings[i].name);
+			xstats[count].name[0] = '\0';
 			xstats[count].value =
 				*(uint64_t *)(((char *)&hw_stats->q[q]) +
 				fm10k_hw_stats_rx_q_strings[i].offset);
 			count++;
 		}
 		for (i = 0; i < FM10K_NB_TX_Q_XSTATS; i++) {
-			snprintf(xstats[count].name, sizeof(xstats[count].name),
-				 "tx_q%u_%s", q,
-				 fm10k_hw_stats_tx_q_strings[i].name);
+			xstats[count].name[0] = '\0';
 			xstats[count].value =
 				*(uint64_t *)(((char *)&hw_stats->q[q]) +
 				fm10k_hw_stats_tx_q_strings[i].offset);
@@ -2629,6 +2665,7 @@ static const struct eth_dev_ops fm10k_eth_dev_ops = {
 	.allmulticast_disable   = fm10k_dev_allmulticast_disable,
 	.stats_get		= fm10k_stats_get,
 	.xstats_get		= fm10k_xstats_get,
+	.xstats_get_names	= fm10k_xstats_get_names,
 	.stats_reset		= fm10k_stats_reset,
 	.xstats_reset		= fm10k_stats_reset,
 	.link_update		= fm10k_link_update,
-- 
2.5.5

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

* [PATCH v4 5/8] drivers/net/i40e: change xstats to use integer ids
  2016-06-13 15:51     ` [PATCH v4 0/8] " Remy Horton
                         ` (3 preceding siblings ...)
  2016-06-13 15:51       ` [PATCH v4 4/8] drivers/net/fm10k: " Remy Horton
@ 2016-06-13 15:51       ` Remy Horton
  2016-06-13 15:51       ` [PATCH v4 6/8] drivers/net/virtio: " Remy Horton
                         ` (3 subsequent siblings)
  8 siblings, 0 replies; 71+ messages in thread
From: Remy Horton @ 2016-06-13 15:51 UTC (permalink / raw)
  To: dev, Helin Zhang, Thomas Monjalon

The current extended ethernet statistics fetching involve doing several
string operations, which causes performance issues if there are lots of
statistics and/or network interfaces. This patch changes the i40e driver
to use the new API that seperates name string and value queries.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c    | 82 ++++++++++++++++++++++++++++++++-------
 drivers/net/i40e/i40e_ethdev_vf.c | 26 +++++++++++--
 2 files changed, 91 insertions(+), 17 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 24777d5..d712bbe 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -306,6 +306,9 @@ static void i40e_dev_stats_get(struct rte_eth_dev *dev,
 			       struct rte_eth_stats *stats);
 static int i40e_dev_xstats_get(struct rte_eth_dev *dev,
 			       struct rte_eth_xstats *xstats, unsigned n);
+static int i40e_dev_xstats_get_names(struct rte_eth_dev *dev,
+				     struct rte_eth_xstat_name *xstats_names,
+				     unsigned limit);
 static void i40e_dev_stats_reset(struct rte_eth_dev *dev);
 static int i40e_dev_queue_stats_mapping_set(struct rte_eth_dev *dev,
 					    uint16_t queue_id,
@@ -467,6 +470,7 @@ static const struct eth_dev_ops i40e_eth_dev_ops = {
 	.link_update                  = i40e_dev_link_update,
 	.stats_get                    = i40e_dev_stats_get,
 	.xstats_get                   = i40e_dev_xstats_get,
+	.xstats_get_names             = i40e_dev_xstats_get_names,
 	.stats_reset                  = i40e_dev_stats_reset,
 	.xstats_reset                 = i40e_dev_stats_reset,
 	.queue_stats_mapping_set      = i40e_dev_queue_stats_mapping_set,
@@ -2205,6 +2209,60 @@ i40e_xstats_calc_num(void)
 		(I40E_NB_TXQ_PRIO_XSTATS * 8);
 }
 
+static int i40e_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
+				     struct rte_eth_xstat_name *xstats_names,
+				     __rte_unused unsigned limit)
+{
+	unsigned count = 0;
+	unsigned i, prio;
+
+	if (xstats_names == NULL)
+		return i40e_xstats_calc_num();
+
+	/* Note: limit checked in rte_eth_xstats_names() */
+
+	/* Get stats from i40e_eth_stats struct */
+	for (i = 0; i < I40E_NB_ETH_XSTATS; i++) {
+		snprintf(xstats_names[count].name,
+			 sizeof(xstats_names[count].name),
+			 "%s", rte_i40e_stats_strings[i].name);
+		xstats_names[count].id = count;
+		count++;
+	}
+
+	/* Get individiual stats from i40e_hw_port struct */
+	for (i = 0; i < I40E_NB_HW_PORT_XSTATS; i++) {
+		snprintf(xstats_names[count].name,
+			sizeof(xstats_names[count].name),
+			 "%s", rte_i40e_hw_port_strings[i].name);
+		xstats_names[count].id = count;
+		count++;
+	}
+
+	for (i = 0; i < I40E_NB_RXQ_PRIO_XSTATS; i++) {
+		for (prio = 0; prio < 8; prio++) {
+			snprintf(xstats_names[count].name,
+				 sizeof(xstats_names[count].name),
+				 "rx_priority%u_%s", prio,
+				 rte_i40e_rxq_prio_strings[i].name);
+			xstats_names[count].id = count;
+			count++;
+		}
+	}
+
+	for (i = 0; i < I40E_NB_TXQ_PRIO_XSTATS; i++) {
+		for (prio = 0; prio < 8; prio++) {
+			snprintf(xstats_names[count].name,
+				 sizeof(xstats_names[count].name),
+				 "tx_priority%u_%s", prio,
+				 rte_i40e_txq_prio_strings[i].name);
+			xstats_names[count].id = count;
+			count++;
+		}
+	}
+	return count;
+}
+
 static int
 i40e_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 		    unsigned n)
@@ -2227,8 +2285,8 @@ i40e_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 
 	/* Get stats from i40e_eth_stats struct */
 	for (i = 0; i < I40E_NB_ETH_XSTATS; i++) {
-		snprintf(xstats[count].name, sizeof(xstats[count].name),
-			 "%s", rte_i40e_stats_strings[i].name);
+		xstats[count].name[0] = '\0';
+		xstats[count].id = count;
 		xstats[count].value = *(uint64_t *)(((char *)&hw_stats->eth) +
 			rte_i40e_stats_strings[i].offset);
 		count++;
@@ -2236,19 +2294,17 @@ i40e_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 
 	/* Get individiual stats from i40e_hw_port struct */
 	for (i = 0; i < I40E_NB_HW_PORT_XSTATS; i++) {
-		snprintf(xstats[count].name, sizeof(xstats[count].name),
-			 "%s", rte_i40e_hw_port_strings[i].name);
+		xstats[count].name[0] = '\0';
+		xstats[count].id = count;
 		xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
-				rte_i40e_hw_port_strings[i].offset);
+			rte_i40e_hw_port_strings[i].offset);
 		count++;
 	}
 
 	for (i = 0; i < I40E_NB_RXQ_PRIO_XSTATS; i++) {
 		for (prio = 0; prio < 8; prio++) {
-			snprintf(xstats[count].name,
-				 sizeof(xstats[count].name),
-				 "rx_priority%u_%s", prio,
-				 rte_i40e_rxq_prio_strings[i].name);
+			xstats[count].name[0] = '\0';
+			xstats[count].id = count;
 			xstats[count].value =
 				*(uint64_t *)(((char *)hw_stats) +
 				rte_i40e_rxq_prio_strings[i].offset +
@@ -2259,10 +2315,8 @@ i40e_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 
 	for (i = 0; i < I40E_NB_TXQ_PRIO_XSTATS; i++) {
 		for (prio = 0; prio < 8; prio++) {
-			snprintf(xstats[count].name,
-				 sizeof(xstats[count].name),
-				 "tx_priority%u_%s", prio,
-				 rte_i40e_txq_prio_strings[i].name);
+			xstats[count].name[0] = '\0';
+			xstats[count].id = count;
 			xstats[count].value =
 				*(uint64_t *)(((char *)hw_stats) +
 				rte_i40e_txq_prio_strings[i].offset +
diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
index 90682ac..4c5e45e 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -112,6 +112,9 @@ static void i40evf_dev_stats_get(struct rte_eth_dev *dev,
 				struct rte_eth_stats *stats);
 static int i40evf_dev_xstats_get(struct rte_eth_dev *dev,
 				 struct rte_eth_xstats *xstats, unsigned n);
+static int i40evf_dev_xstats_get_names(struct rte_eth_dev *dev,
+				       struct rte_eth_xstat_name *xstats_names,
+				       unsigned limit);
 static void i40evf_dev_xstats_reset(struct rte_eth_dev *dev);
 static int i40evf_vlan_filter_set(struct rte_eth_dev *dev,
 				  uint16_t vlan_id, int on);
@@ -196,6 +199,7 @@ static const struct eth_dev_ops i40evf_eth_dev_ops = {
 	.link_update          = i40evf_dev_link_update,
 	.stats_get            = i40evf_dev_stats_get,
 	.xstats_get           = i40evf_dev_xstats_get,
+	.xstats_get_names     = i40evf_dev_xstats_get_names,
 	.xstats_reset         = i40evf_dev_xstats_reset,
 	.dev_close            = i40evf_dev_close,
 	.dev_infos_get        = i40evf_dev_info_get,
@@ -984,6 +988,22 @@ i40evf_dev_xstats_reset(struct rte_eth_dev *dev)
 	vf->vsi.eth_stats_offset = vf->vsi.eth_stats;
 }
 
+static int i40evf_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
+				      struct rte_eth_xstat_name *xstats_names,
+				      __rte_unused unsigned limit)
+{
+	unsigned i;
+
+	if (xstats_names != NULL)
+		for (i = 0; i < I40EVF_NB_XSTATS; i++) {
+			snprintf(xstats_names[i].name,
+				sizeof(xstats_names[i].name),
+				"%s", rte_i40evf_stats_strings[i].name);
+			xstats_names[i].id = i;
+		}
+	return I40EVF_NB_XSTATS;
+}
+
 static int i40evf_dev_xstats_get(struct rte_eth_dev *dev,
 				 struct rte_eth_xstats *xstats, unsigned n)
 {
@@ -1003,8 +1023,8 @@ static int i40evf_dev_xstats_get(struct rte_eth_dev *dev,
 
 	/* loop over xstats array and values from pstats */
 	for (i = 0; i < I40EVF_NB_XSTATS; i++) {
-		snprintf(xstats[i].name, sizeof(xstats[i].name),
-			 "%s", rte_i40evf_stats_strings[i].name);
+		xstats[i].name[0] = '\0';
+		xstats[i].id = i;
 		xstats[i].value = *(uint64_t *)(((char *)pstats) +
 			rte_i40evf_stats_strings[i].offset);
 	}
-- 
2.5.5

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

* [PATCH v4 6/8] drivers/net/virtio: change xstats to use integer ids
  2016-06-13 15:51     ` [PATCH v4 0/8] " Remy Horton
                         ` (4 preceding siblings ...)
  2016-06-13 15:51       ` [PATCH v4 5/8] drivers/net/i40e: " Remy Horton
@ 2016-06-13 15:51       ` Remy Horton
  2016-06-13 15:52       ` [PATCH v4 7/8] rte: change xstats usage to new API Remy Horton
                         ` (2 subsequent siblings)
  8 siblings, 0 replies; 71+ messages in thread
From: Remy Horton @ 2016-06-13 15:51 UTC (permalink / raw)
  To: dev, Huawei Xie, Thomas Monjalon

The current extended ethernet statistics fetching involve doing several
string operations, which causes performance issues if there are lots of
statistics and/or network interfaces. This patch changes the virtio driver
to use the new API that seperates name string and value queries.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 drivers/net/virtio/virtio_ethdev.c | 62 +++++++++++++++++++++++++++++++++-----
 1 file changed, 55 insertions(+), 7 deletions(-)

diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c
index c3fb628..83df025 100644
--- a/drivers/net/virtio/virtio_ethdev.c
+++ b/drivers/net/virtio/virtio_ethdev.c
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -80,6 +80,9 @@ static void virtio_dev_stats_get(struct rte_eth_dev *dev,
 				 struct rte_eth_stats *stats);
 static int virtio_dev_xstats_get(struct rte_eth_dev *dev,
 				 struct rte_eth_xstats *xstats, unsigned n);
+static int virtio_dev_xstats_get_names(struct rte_eth_dev *dev,
+				       struct rte_eth_xstat_name *xstats_names,
+				       unsigned limit);
 static void virtio_dev_stats_reset(struct rte_eth_dev *dev);
 static void virtio_dev_free_mbufs(struct rte_eth_dev *dev);
 static int virtio_vlan_filter_set(struct rte_eth_dev *dev,
@@ -615,6 +618,7 @@ static const struct eth_dev_ops virtio_eth_dev_ops = {
 	.dev_infos_get           = virtio_dev_info_get,
 	.stats_get               = virtio_dev_stats_get,
 	.xstats_get              = virtio_dev_xstats_get,
+	.xstats_get_names        = virtio_dev_xstats_get_names,
 	.stats_reset             = virtio_dev_stats_reset,
 	.xstats_reset            = virtio_dev_stats_reset,
 	.link_update             = virtio_dev_link_update,
@@ -708,6 +712,52 @@ virtio_update_stats(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
 	stats->rx_nombuf = dev->data->rx_mbuf_alloc_failed;
 }
 
+static int virtio_dev_xstats_get_names(struct rte_eth_dev *dev,
+				       struct rte_eth_xstat_name *xstats_names,
+				       __rte_unused unsigned limit)
+{
+	unsigned i;
+	unsigned count = 0;
+	unsigned t;
+
+	unsigned nstats = dev->data->nb_tx_queues * VIRTIO_NB_Q_XSTATS +
+		dev->data->nb_rx_queues * VIRTIO_NB_Q_XSTATS;
+
+	if (xstats_names == NULL) {
+		/* Note: limit checked in rte_eth_xstats_names() */
+
+		for (i = 0; i < dev->data->nb_rx_queues; i++) {
+			struct virtqueue *rxvq = dev->data->rx_queues[i];
+			if (rxvq == NULL)
+				continue;
+			for (t = 0; t < VIRTIO_NB_Q_XSTATS; t++) {
+				snprintf(xstats_names[count].name,
+					sizeof(xstats_names[count].name),
+					"rx_q%u_%s", i,
+					rte_virtio_q_stat_strings[t].name);
+				xstats_names[count].id = count;
+				count++;
+			}
+		}
+
+		for (i = 0; i < dev->data->nb_tx_queues; i++) {
+			struct virtqueue *txvq = dev->data->tx_queues[i];
+			if (txvq == NULL)
+				continue;
+			for (t = 0; t < VIRTIO_NB_Q_XSTATS; t++) {
+				snprintf(xstats_names[count].name,
+					sizeof(xstats_names[count].name),
+					"tx_q%u_%s", i,
+					rte_virtio_q_stat_strings[t].name);
+				xstats_names[count].id = count;
+				count++;
+			}
+		}
+		return count;
+	}
+	return nstats;
+}
+
 static int
 virtio_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 		      unsigned n)
@@ -730,9 +780,8 @@ virtio_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 		unsigned t;
 
 		for (t = 0; t < VIRTIO_NB_Q_XSTATS; t++) {
-			snprintf(xstats[count].name, sizeof(xstats[count].name),
-				 "rx_q%u_%s", i,
-				 rte_virtio_q_stat_strings[t].name);
+			xstats[count].name[0] = '\0';
+			xstats[count].id = count;
 			xstats[count].value = *(uint64_t *)(((char *)rxvq) +
 				rte_virtio_q_stat_strings[t].offset);
 			count++;
@@ -748,9 +797,8 @@ virtio_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 		unsigned t;
 
 		for (t = 0; t < VIRTIO_NB_Q_XSTATS; t++) {
-			snprintf(xstats[count].name, sizeof(xstats[count].name),
-				 "tx_q%u_%s", i,
-				 rte_virtio_q_stat_strings[t].name);
+			xstats[count].name[0] = '\0';
+			xstats[count].id = count;
 			xstats[count].value = *(uint64_t *)(((char *)txvq) +
 				rte_virtio_q_stat_strings[t].offset);
 			count++;
-- 
2.5.5

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

* [PATCH v4 7/8] rte: change xstats usage to new API
  2016-06-13 15:51     ` [PATCH v4 0/8] " Remy Horton
                         ` (5 preceding siblings ...)
  2016-06-13 15:51       ` [PATCH v4 6/8] drivers/net/virtio: " Remy Horton
@ 2016-06-13 15:52       ` Remy Horton
  2016-06-15  9:13         ` Thomas Monjalon
  2016-06-13 15:52       ` [PATCH v4 8/8] doc: update xstats documentation Remy Horton
  2016-06-15 15:25       ` [PATCH v5 0/7] Remove string operations from xstats Remy Horton
  8 siblings, 1 reply; 71+ messages in thread
From: Remy Horton @ 2016-06-13 15:52 UTC (permalink / raw)
  To: dev, Pablo de Lara, Maryam Tahhan, Thomas Monjalon, Helin Zhang,
	Wenzhuo Lu, Jing Chen, Huawei Xie

The current extended ethernet statistics fetching involve doing several
string operations, which causes performance issues if there are lots of
statistics and/or network interfaces. This patch changes the test-pmd
and proc_info applications to use the new xstats API, and removes
deprecated code associated with the old API.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 app/proc_info/main.c               | 29 +++++++++++++++++---
 app/test-pmd/config.c              | 54 +++++++++++++++++++++++++++++---------
 drivers/net/e1000/igb_ethdev.c     | 10 +++----
 drivers/net/fm10k/fm10k_ethdev.c   |  5 +---
 drivers/net/i40e/i40e_ethdev.c     |  8 ++----
 drivers/net/i40e/i40e_ethdev_vf.c  |  5 ++--
 drivers/net/ixgbe/ixgbe_ethdev.c   | 11 +++-----
 drivers/net/virtio/virtio_ethdev.c |  6 ++---
 lib/librte_ether/rte_ethdev.c      |  5 +---
 lib/librte_ether/rte_ethdev.h      |  7 +++--
 10 files changed, 85 insertions(+), 55 deletions(-)

diff --git a/app/proc_info/main.c b/app/proc_info/main.c
index 5f83092..f2063fa 100644
--- a/app/proc_info/main.c
+++ b/app/proc_info/main.c
@@ -1,7 +1,7 @@
 /*
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -243,11 +243,13 @@ nic_stats_clear(uint8_t port_id)
 static void
 nic_xstats_display(uint8_t port_id)
 {
-	struct rte_eth_xstats *xstats;
+	struct rte_eth_xstat_name *xstats_names;
+	struct rte_eth_xstat *xstats;
 	int len, ret, i;
+	int idx_name;
 	static const char *nic_stats_border = "########################";
 
-	len = rte_eth_xstats_get(port_id, NULL, 0);
+	len = rte_eth_xstats_get_names(port_id, NULL, 0);
 	if (len < 0) {
 		printf("Cannot get xstats count\n");
 		return;
@@ -258,6 +260,18 @@ nic_xstats_display(uint8_t port_id)
 		return;
 	}
 
+	xstats_names = malloc(sizeof(struct rte_eth_xstat_name) * len);
+	if (xstats_names == NULL) {
+		printf("Cannot allocate memory for xstat names\n");
+		free(xstats);
+		return;
+	}
+	if (len != rte_eth_xstats_get_names(
+			port_id, xstats_names, len)) {
+		printf("Cannot get xstat names\n");
+		return;
+	}
+
 	printf("###### NIC extended statistics for port %-2d #########\n",
 			   port_id);
 	printf("%s############################\n",
@@ -270,11 +284,18 @@ nic_xstats_display(uint8_t port_id)
 	}
 
 	for (i = 0; i < len; i++)
-		printf("%s: %"PRIu64"\n", xstats[i].name, xstats[i].value);
+		for (idx_name = 0; idx_name < len; idx_name++)
+			if (xstats_names[idx_name].id == xstats[i].id) {
+				printf("%s: %"PRIu64"\n",
+					xstats_names[idx_name].name,
+					xstats[i].value);
+				break;
+			}
 
 	printf("%s############################\n",
 			   nic_stats_border);
 	free(xstats);
+	free(xstats_names);
 }
 
 static void
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 1c552e4..8ddec07 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -232,29 +232,57 @@ nic_stats_clear(portid_t port_id)
 void
 nic_xstats_display(portid_t port_id)
 {
-	struct rte_eth_xstats *xstats;
-	int len, ret, i;
+	struct rte_eth_xstat *xstats;
+	int cnt_xstats, idx_xstat, idx_name;
+	struct rte_eth_xstat_name *xstats_names;
 
 	printf("###### NIC extended statistics for port %-2d\n", port_id);
+	if (!rte_eth_dev_is_valid_port(port_id)) {
+		printf("Error: Invalid port number %i\n", port_id);
+		return;
+	}
+
+	/* Get count */
+	cnt_xstats = rte_eth_xstats_get_names(port_id, NULL, 0);
+	if (cnt_xstats  < 0) {
+		printf("Error: Cannot get count of xstats\n");
+		return;
+	}
 
-	len = rte_eth_xstats_get(port_id, NULL, 0);
-	if (len < 0) {
-		printf("Cannot get xstats count\n");
+	/* Get id-name lookup table */
+	xstats_names = malloc(sizeof(struct rte_eth_xstat_name) * cnt_xstats);
+	if (xstats_names == NULL) {
+		printf("Cannot allocate memory for xstats lookup\n");
 		return;
 	}
-	xstats = malloc(sizeof(xstats[0]) * len);
+	if (cnt_xstats != rte_eth_xstats_get_names(
+			port_id, xstats_names, cnt_xstats)) {
+		printf("Error: Cannot get xstats lookup\n");
+		return;
+	}
+
+	/* Get stats themselves */
+	xstats = malloc(sizeof(struct rte_eth_xstat) * cnt_xstats);
 	if (xstats == NULL) {
 		printf("Cannot allocate memory for xstats\n");
+		free(xstats_names);
 		return;
 	}
-	ret = rte_eth_xstats_get(port_id, xstats, len);
-	if (ret < 0 || ret > len) {
-		printf("Cannot get xstats\n");
-		free(xstats);
+	if (cnt_xstats != rte_eth_xstats_get(port_id, xstats, cnt_xstats)) {
+		printf("Error: Unable to get xstats\n");
 		return;
 	}
-	for (i = 0; i < len; i++)
-		printf("%s: %"PRIu64"\n", xstats[i].name, xstats[i].value);
+
+	/* Display xstats */
+	for (idx_xstat = 0; idx_xstat < cnt_xstats; idx_xstat++)
+		for (idx_name = 0; idx_name < cnt_xstats; idx_name++)
+			if (xstats_names[idx_name].id == xstats[idx_xstat].id) {
+				printf("%s: %"PRIu64"\n",
+					xstats_names[idx_name].name,
+					xstats[idx_xstat].value);
+				break;
+			}
+	free(xstats_names);
 	free(xstats);
 }
 
diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index dffa04f..b822992 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -99,7 +99,7 @@ static int  eth_igb_link_update(struct rte_eth_dev *dev,
 static void eth_igb_stats_get(struct rte_eth_dev *dev,
 				struct rte_eth_stats *rte_stats);
 static int eth_igb_xstats_get(struct rte_eth_dev *dev,
-			      struct rte_eth_xstats *xstats, unsigned n);
+			      struct rte_eth_xstat *xstats, unsigned n);
 static int eth_igb_xstats_get_names(struct rte_eth_dev *dev,
 				    struct rte_eth_xstat_name *xstats_names,
 				    unsigned limit);
@@ -167,7 +167,7 @@ static int eth_igbvf_link_update(struct e1000_hw *hw);
 static void eth_igbvf_stats_get(struct rte_eth_dev *dev,
 				struct rte_eth_stats *rte_stats);
 static int eth_igbvf_xstats_get(struct rte_eth_dev *dev,
-				struct rte_eth_xstats *xstats, unsigned n);
+				struct rte_eth_xstat *xstats, unsigned n);
 static int eth_igbvf_xstats_get_names(struct rte_eth_dev *dev,
 				      struct rte_eth_xstat_name *xstats_names,
 				      unsigned limit);
@@ -1720,7 +1720,7 @@ static int eth_igb_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 }
 
 static int
-eth_igb_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
+eth_igb_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
 		   unsigned n)
 {
 	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
@@ -1741,7 +1741,6 @@ eth_igb_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 
 	/* Extended stats */
 	for (i = 0; i < IGB_NB_XSTATS; i++) {
-		xstats[i].name[0] = '\0';
 		xstats[i].id = i;
 		xstats[i].value = *(uint64_t *)(((char *)hw_stats) +
 			rte_igb_stats_strings[i].offset);
@@ -1807,7 +1806,7 @@ static int eth_igbvf_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 }
 
 static int
-eth_igbvf_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
+eth_igbvf_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
 		     unsigned n)
 {
 	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
@@ -1824,7 +1823,6 @@ eth_igbvf_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 		return 0;
 
 	for (i = 0; i < IGBVF_NB_XSTATS; i++) {
-		xstats[i].name[0] = '\0';
 		xstats[i].id = i;
 		xstats[i].value = *(uint64_t *)(((char *)hw_stats) +
 			rte_igbvf_stats_strings[i].offset);
diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c
index e07c1ec..ce053b0 100644
--- a/drivers/net/fm10k/fm10k_ethdev.c
+++ b/drivers/net/fm10k/fm10k_ethdev.c
@@ -1298,7 +1298,7 @@ static int fm10k_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 }
 
 static int
-fm10k_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
+fm10k_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
 		 unsigned n)
 {
 	struct fm10k_hw_stats *hw_stats =
@@ -1310,7 +1310,6 @@ fm10k_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 
 	/* Global stats */
 	for (i = 0; i < FM10K_NB_HW_XSTATS; i++) {
-		xstats[count].name[0] = '\0';
 		xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
 			fm10k_hw_stats_strings[count].offset);
 		count++;
@@ -1319,14 +1318,12 @@ fm10k_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 	/* PF queue stats */
 	for (q = 0; q < FM10K_MAX_QUEUES_PF; q++) {
 		for (i = 0; i < FM10K_NB_RX_Q_XSTATS; i++) {
-			xstats[count].name[0] = '\0';
 			xstats[count].value =
 				*(uint64_t *)(((char *)&hw_stats->q[q]) +
 				fm10k_hw_stats_rx_q_strings[i].offset);
 			count++;
 		}
 		for (i = 0; i < FM10K_NB_TX_Q_XSTATS; i++) {
-			xstats[count].name[0] = '\0';
 			xstats[count].value =
 				*(uint64_t *)(((char *)&hw_stats->q[q]) +
 				fm10k_hw_stats_tx_q_strings[i].offset);
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index d712bbe..f94ad87 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -305,7 +305,7 @@ static int i40e_dev_set_link_down(struct rte_eth_dev *dev);
 static void i40e_dev_stats_get(struct rte_eth_dev *dev,
 			       struct rte_eth_stats *stats);
 static int i40e_dev_xstats_get(struct rte_eth_dev *dev,
-			       struct rte_eth_xstats *xstats, unsigned n);
+			       struct rte_eth_xstat *xstats, unsigned n);
 static int i40e_dev_xstats_get_names(struct rte_eth_dev *dev,
 				     struct rte_eth_xstat_name *xstats_names,
 				     unsigned limit);
@@ -2264,7 +2264,7 @@ static int i40e_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 }
 
 static int
-i40e_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
+i40e_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
 		    unsigned n)
 {
 	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
@@ -2285,7 +2285,6 @@ i40e_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 
 	/* Get stats from i40e_eth_stats struct */
 	for (i = 0; i < I40E_NB_ETH_XSTATS; i++) {
-		xstats[count].name[0] = '\0';
 		xstats[count].id = count;
 		xstats[count].value = *(uint64_t *)(((char *)&hw_stats->eth) +
 			rte_i40e_stats_strings[i].offset);
@@ -2294,7 +2293,6 @@ i40e_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 
 	/* Get individiual stats from i40e_hw_port struct */
 	for (i = 0; i < I40E_NB_HW_PORT_XSTATS; i++) {
-		xstats[count].name[0] = '\0';
 		xstats[count].id = count;
 		xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
 			rte_i40e_hw_port_strings[i].offset);
@@ -2303,7 +2301,6 @@ i40e_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 
 	for (i = 0; i < I40E_NB_RXQ_PRIO_XSTATS; i++) {
 		for (prio = 0; prio < 8; prio++) {
-			xstats[count].name[0] = '\0';
 			xstats[count].id = count;
 			xstats[count].value =
 				*(uint64_t *)(((char *)hw_stats) +
@@ -2315,7 +2312,6 @@ i40e_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 
 	for (i = 0; i < I40E_NB_TXQ_PRIO_XSTATS; i++) {
 		for (prio = 0; prio < 8; prio++) {
-			xstats[count].name[0] = '\0';
 			xstats[count].id = count;
 			xstats[count].value =
 				*(uint64_t *)(((char *)hw_stats) +
diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
index 4c5e45e..37af399 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -111,7 +111,7 @@ static int i40evf_dev_link_update(struct rte_eth_dev *dev,
 static void i40evf_dev_stats_get(struct rte_eth_dev *dev,
 				struct rte_eth_stats *stats);
 static int i40evf_dev_xstats_get(struct rte_eth_dev *dev,
-				 struct rte_eth_xstats *xstats, unsigned n);
+				 struct rte_eth_xstat *xstats, unsigned n);
 static int i40evf_dev_xstats_get_names(struct rte_eth_dev *dev,
 				       struct rte_eth_xstat_name *xstats_names,
 				       unsigned limit);
@@ -1005,7 +1005,7 @@ static int i40evf_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 }
 
 static int i40evf_dev_xstats_get(struct rte_eth_dev *dev,
-				 struct rte_eth_xstats *xstats, unsigned n)
+				 struct rte_eth_xstat *xstats, unsigned n)
 {
 	int ret;
 	unsigned i;
@@ -1023,7 +1023,6 @@ static int i40evf_dev_xstats_get(struct rte_eth_dev *dev,
 
 	/* loop over xstats array and values from pstats */
 	for (i = 0; i < I40EVF_NB_XSTATS; i++) {
-		xstats[i].name[0] = '\0';
 		xstats[i].id = i;
 		xstats[i].value = *(uint64_t *)(((char *)pstats) +
 			rte_i40evf_stats_strings[i].offset);
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 9e73492..125c257 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -174,9 +174,9 @@ static int ixgbe_dev_link_update(struct rte_eth_dev *dev,
 static void ixgbe_dev_stats_get(struct rte_eth_dev *dev,
 				struct rte_eth_stats *stats);
 static int ixgbe_dev_xstats_get(struct rte_eth_dev *dev,
-				struct rte_eth_xstats *xstats, unsigned n);
+				struct rte_eth_xstat *xstats, unsigned n);
 static int ixgbevf_dev_xstats_get(struct rte_eth_dev *dev,
-				  struct rte_eth_xstats *xstats, unsigned n);
+				  struct rte_eth_xstat *xstats, unsigned n);
 static void ixgbe_dev_stats_reset(struct rte_eth_dev *dev);
 static void ixgbe_dev_xstats_reset(struct rte_eth_dev *dev);
 static int ixgbe_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
@@ -2775,7 +2775,7 @@ static int ixgbevf_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 }
 
 static int
-ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
+ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
 					 unsigned n)
 {
 	struct ixgbe_hw *hw =
@@ -2808,7 +2808,6 @@ ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 	count = 0;
 	for (i = 0; i < IXGBE_NB_HW_STATS; i++) {
 		xstats[count].id = count;
-		xstats[count].name[0] = '\0';
 		xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
 				rte_ixgbe_stats_strings[i].offset);
 		count++;
@@ -2818,7 +2817,6 @@ ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 	for (stat = 0; stat < IXGBE_NB_RXQ_PRIO_STATS; stat++) {
 		for (i = 0; i < IXGBE_NB_RXQ_PRIO_VALUES; i++) {
 			xstats[count].id = count;
-			xstats[count].name[0] = '\0';
 			xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
 					rte_ixgbe_rxq_strings[stat].offset +
 					(sizeof(uint64_t) * i));
@@ -2830,7 +2828,6 @@ ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 	for (stat = 0; stat < IXGBE_NB_TXQ_PRIO_STATS; stat++) {
 		for (i = 0; i < IXGBE_NB_TXQ_PRIO_VALUES; i++) {
 			xstats[count].id = count;
-			xstats[count].name[0] = '\0';
 			xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
 					rte_ixgbe_txq_strings[stat].offset +
 					(sizeof(uint64_t) * i));
@@ -2884,7 +2881,7 @@ ixgbevf_update_stats(struct rte_eth_dev *dev)
 }
 
 static int
-ixgbevf_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
+ixgbevf_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
 		       unsigned n)
 {
 	struct ixgbevf_hw_stats *hw_stats = (struct ixgbevf_hw_stats *)
diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c
index 83df025..a833740 100644
--- a/drivers/net/virtio/virtio_ethdev.c
+++ b/drivers/net/virtio/virtio_ethdev.c
@@ -79,7 +79,7 @@ static void virtio_get_hwaddr(struct virtio_hw *hw);
 static void virtio_dev_stats_get(struct rte_eth_dev *dev,
 				 struct rte_eth_stats *stats);
 static int virtio_dev_xstats_get(struct rte_eth_dev *dev,
-				 struct rte_eth_xstats *xstats, unsigned n);
+				 struct rte_eth_xstat *xstats, unsigned n);
 static int virtio_dev_xstats_get_names(struct rte_eth_dev *dev,
 				       struct rte_eth_xstat_name *xstats_names,
 				       unsigned limit);
@@ -759,7 +759,7 @@ static int virtio_dev_xstats_get_names(struct rte_eth_dev *dev,
 }
 
 static int
-virtio_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
+virtio_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
 		      unsigned n)
 {
 	unsigned i;
@@ -780,7 +780,6 @@ virtio_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 		unsigned t;
 
 		for (t = 0; t < VIRTIO_NB_Q_XSTATS; t++) {
-			xstats[count].name[0] = '\0';
 			xstats[count].id = count;
 			xstats[count].value = *(uint64_t *)(((char *)rxvq) +
 				rte_virtio_q_stat_strings[t].offset);
@@ -797,7 +796,6 @@ virtio_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 		unsigned t;
 
 		for (t = 0; t < VIRTIO_NB_Q_XSTATS; t++) {
-			xstats[count].name[0] = '\0';
 			xstats[count].id = count;
 			xstats[count].value = *(uint64_t *)(((char *)txvq) +
 				rte_virtio_q_stat_strings[t].offset);
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 79a01cc..afe1291 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -1584,7 +1584,7 @@ rte_eth_xstats_get_names(uint8_t port_id,
 
 /* retrieve ethdev extended statistics */
 int
-rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
+rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstat *xstats,
 	unsigned n)
 {
 	struct rte_eth_stats eth_stats;
@@ -1626,7 +1626,6 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
 		stats_ptr = RTE_PTR_ADD(&eth_stats,
 					rte_stats_strings[i].offset);
 		val = *stats_ptr;
-		xstats[count].name[0] = '\0';
 		xstats[count].id = count + xcount;
 		xstats[count++].value = val;
 	}
@@ -1638,7 +1637,6 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
 					rte_rxq_stats_strings[i].offset +
 					q * sizeof(uint64_t));
 			val = *stats_ptr;
-			xstats[count].name[0] = '\0';
 			xstats[count].id = count + xcount;
 			xstats[count++].value = val;
 		}
@@ -1651,7 +1649,6 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
 					rte_txq_stats_strings[i].offset +
 					q * sizeof(uint64_t));
 			val = *stats_ptr;
-			xstats[count].name[0] = '\0';
 			xstats[count].id = count + xcount;
 			xstats[count++].value = val;
 		}
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 7d8ce3c..76b9d61 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -914,8 +914,7 @@ struct rte_eth_txq_info {
  * statistics that are not provided in the generic rte_eth_stats
  * structure.
  */
-struct rte_eth_xstats {
-	char name[RTE_ETH_XSTATS_NAME_SIZE];
+struct rte_eth_xstat {
 	uint64_t id;
 	uint64_t value;
 };
@@ -1060,7 +1059,7 @@ typedef void (*eth_stats_reset_t)(struct rte_eth_dev *dev);
 /**< @internal Reset global I/O statistics of an Ethernet device to 0. */
 
 typedef int (*eth_xstats_get_t)(struct rte_eth_dev *dev,
-	struct rte_eth_xstats *stats, unsigned n);
+	struct rte_eth_xstat *stats, unsigned n);
 /**< @internal Get extended stats of an Ethernet device. */
 
 typedef void (*eth_xstats_reset_t)(struct rte_eth_dev *dev);
@@ -2308,7 +2307,7 @@ int rte_eth_xstats_get_names(uint8_t port_id,
  *     shall not be used by the caller.
  *   - negative value on error (invalid port id)
  */
-int rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
+int rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstat *xstats,
 		unsigned n);
 
 /**
-- 
2.5.5

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

* [PATCH v4 8/8] doc: update xstats documentation
  2016-06-13 15:51     ` [PATCH v4 0/8] " Remy Horton
                         ` (6 preceding siblings ...)
  2016-06-13 15:52       ` [PATCH v4 7/8] rte: change xstats usage to new API Remy Horton
@ 2016-06-13 15:52       ` Remy Horton
  2016-06-14 14:06         ` Mcnamara, John
  2016-06-15 15:25       ` [PATCH v5 0/7] Remove string operations from xstats Remy Horton
  8 siblings, 1 reply; 71+ messages in thread
From: Remy Horton @ 2016-06-13 15:52 UTC (permalink / raw)
  To: dev, John McNamara, Thomas Monjalon

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 doc/guides/prog_guide/poll_mode_drv.rst | 25 +++++++++++++++++++++----
 1 file changed, 21 insertions(+), 4 deletions(-)

diff --git a/doc/guides/prog_guide/poll_mode_drv.rst b/doc/guides/prog_guide/poll_mode_drv.rst
index 7698692..802fb8f 100644
--- a/doc/guides/prog_guide/poll_mode_drv.rst
+++ b/doc/guides/prog_guide/poll_mode_drv.rst
@@ -299,10 +299,27 @@ Extended Statistics API
 ~~~~~~~~~~~~~~~~~~~~~~~
 
 The extended statistics API allows each individual PMD to expose a unique set
-of statistics. The client of the API provides an array of
-``struct rte_eth_xstats`` type. Each ``struct rte_eth_xstats`` contains a
-string and value pair. The amount of xstats exposed, and position of the
-statistic in the array must remain constant during runtime.
+of statistics. Accessing these from application programs is done via two
+functions:
+
+* ``rte_eth_xstats_get``: Fills in an array of ``struct rte_eth_xstat``
+  with extended statistics.
+* ``rte_eth_xstats_get_names``: Fills in an array of
+  ``struct rte_eth_xstat_name`` with extended statistic name lookup
+  information.
+
+Each ``struct rte_eth_xstat`` contains an identifier and value pair, and
+each ``struct rte_eth_xstat_name`` contains an identifier and string pair.
+Each identifier within ``struct rte_eth_xstat`` must have a corresponding
+entry in ``struct rte_eth_xstat_name`` with a matching identifier. These
+identifiers, as well as the number of extended statistic exposed, must
+remain constant during runtime.
+
+Note that extended statistic identifiers are driver-specific, and hence
+might not be the same for different ports. Although it is expected that
+drivers will make the identifiers used within ``struct rte_eth_xstat`` and
+``struct rte_eth_xstat_name`` entries match the entries' array index, this
+property should not be relied on by applications for lookups.
 
 A naming scheme exists for the strings exposed to clients of the API. This is
 to allow scraping of the API for statistics of interest. The naming scheme uses
-- 
2.5.5

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

* Re: [PATCH v4 8/8] doc: update xstats documentation
  2016-06-13 15:52       ` [PATCH v4 8/8] doc: update xstats documentation Remy Horton
@ 2016-06-14 14:06         ` Mcnamara, John
  0 siblings, 0 replies; 71+ messages in thread
From: Mcnamara, John @ 2016-06-14 14:06 UTC (permalink / raw)
  To: Horton, Remy, dev, Thomas Monjalon

> -----Original Message-----
> From: Horton, Remy
> Sent: Monday, June 13, 2016 4:52 PM
> To: dev@dpdk.org; Mcnamara, John <john.mcnamara@intel.com>; Thomas
> Monjalon <thomas.monjalon@6wind.com>
> Subject: [PATCH v4 8/8] doc: update xstats documentation
> 
> Signed-off-by: Remy Horton <remy.horton@intel.com>

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

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

* Re: [PATCH v4 7/8] rte: change xstats usage to new API
  2016-06-13 15:52       ` [PATCH v4 7/8] rte: change xstats usage to new API Remy Horton
@ 2016-06-15  9:13         ` Thomas Monjalon
  0 siblings, 0 replies; 71+ messages in thread
From: Thomas Monjalon @ 2016-06-15  9:13 UTC (permalink / raw)
  To: Remy Horton
  Cc: dev, Pablo de Lara, Maryam Tahhan, Helin Zhang, Wenzhuo Lu,
	Jing Chen, Huawei Xie

2016-06-13 16:52, Remy Horton:
> The current extended ethernet statistics fetching involve doing several
> string operations, which causes performance issues if there are lots of
> statistics and/or network interfaces. This patch changes the test-pmd
> and proc_info applications to use the new xstats API, and removes
> deprecated code associated with the old API.

There is something wrong which lead to this error:
undefined reference to `rte_eth_xstats_get_names'

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

* Re: [PATCH v4 1/8] rte: change xstats to use integer ids
  2016-06-13 15:51       ` [PATCH v4 1/8] rte: change xstats to use integer ids Remy Horton
@ 2016-06-15  9:19         ` Thomas Monjalon
  0 siblings, 0 replies; 71+ messages in thread
From: Thomas Monjalon @ 2016-06-15  9:19 UTC (permalink / raw)
  To: Remy Horton; +Cc: dev

2016-06-13 16:51, Remy Horton:
> Signed-off-by: Remy Horton <remy.horton@intel.com>

Please insert an explanation of why this change is needed.

[...]
>  /**
> + * Retrieve names of extended statistics of an Ethernet device.
> + *
> + * @param port_id
> + *   The port identifier of the Ethernet device.
> + * @param xstats_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 xstats_names (number of names).
> + * @return
> + *  If successful, number of statistics; negative on error.
> + */

Like in rte_eth_xstats_get(), it should return a positive value if size
is not big enough.

> +int rte_eth_xstats_get_names(uint8_t port_id,
> +		struct rte_eth_xstat_name *xstats_names,
> +		unsigned size);

[...]
> +DPDK_16.07 {
> +	global:
> +
> +	rte_eth_xstats_names;
> +	rte_eth_xstats_count;
> +} DPDK_16.04;

Wrong functions.

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

* [PATCH v5 0/7] Remove string operations from xstats
  2016-06-13 15:51     ` [PATCH v4 0/8] " Remy Horton
                         ` (7 preceding siblings ...)
  2016-06-13 15:52       ` [PATCH v4 8/8] doc: update xstats documentation Remy Horton
@ 2016-06-15 15:25       ` Remy Horton
  2016-06-15 15:25         ` [PATCH v5 1/7] rte: change xstats to use integer ids Remy Horton
                           ` (7 more replies)
  8 siblings, 8 replies; 71+ messages in thread
From: Remy Horton @ 2016-06-15 15:25 UTC (permalink / raw)
  To: dev, Thomas Monjalon, John McNamara

The current extended ethernet statistics fetching involve doing several
string operations, which causes performance issues if there are lots of
statistics and/or network interfaces. This patchset changes the API for
xstats to use integer identifiers instead of strings and implements
this new API for the ixgbe, i40e, e1000, fm10k, and virtio drivers.

--

v5 changes:
* Missing .map file change added (broke shared builds)
* rte_eth_xstats_get_names(): Changed buffer-too-small return value
* Missing commit description added
* Documentation patch squashed (had been ACK'd)

v4 changes:
* rte_eth_xstats_count() removed
* rte_eth_xstats_names() changed to rte_eth_xstats_get_names()
* struct rte_eth_xstats_name renamed to rte_eth_xstat_name
* struct rte_eth_xstats renamed to rte_eth_xstat
* struct rte_eth_dev: .xstats_names renamed to .xstats_get_names
* Other minor local variable name changes
* Documentation updates due to renames
* API changeover patches squashed

v3 changes:
* Corrected ixgbe vf xstats fetching
* Added xstats changes to e1000, f10k, and virtio drivers
* Added cleanup patch that removes now-redundant name field
* Removed ethtool xstats command 
* Removed unused .xstats_count from eth-dev_ops
* Changed test-pmd & proc_info to use new API
* Added documentation update
* Added missing changes to .map file (affected shared lib builds)

v2 changes:
* Fetching xstats count now seperate API function
* Added #define constants for some magic numbers
* Fixed bug with virtual function count fetching
* For non-xstats-supporting drivers, queue stats returned
* Some refactoring/cleanups
* Removed index assumption from example

Remy Horton (7):
  rte: change xstats to use integer ids
  drivers/net/ixgbe: change xstats to use integer ids
  drivers/net/e1000: change xstats to use integer ids
  drivers/net/fm10k: change xstats to use integer ids
  drivers/net/i40e: change xstats to use integer ids
  drivers/net/virtio: change xstats to use integer ids
  rte: change xstats usage to new API

 app/proc_info/main.c                    |  29 +++++++--
 app/test-pmd/config.c                   |  54 ++++++++++++----
 doc/guides/prog_guide/poll_mode_drv.rst |  25 ++++++--
 drivers/net/e1000/igb_ethdev.c          |  58 ++++++++++++++---
 drivers/net/fm10k/fm10k_ethdev.c        |  54 +++++++++++++---
 drivers/net/i40e/i40e_ethdev.c          |  82 +++++++++++++++++++-----
 drivers/net/i40e/i40e_ethdev_vf.c       |  29 +++++++--
 drivers/net/ixgbe/ixgbe_ethdev.c        | 106 ++++++++++++++++++++++++++------
 drivers/net/virtio/virtio_ethdev.c      |  64 ++++++++++++++++---
 lib/librte_ether/rte_ethdev.c           |  92 ++++++++++++++++++++++++---
 lib/librte_ether/rte_ethdev.h           |  48 +++++++++++++--
 lib/librte_ether/rte_ether_version.map  |   6 ++
 12 files changed, 546 insertions(+), 101 deletions(-)

-- 
2.5.5

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

* [PATCH v5 1/7] rte: change xstats to use integer ids
  2016-06-15 15:25       ` [PATCH v5 0/7] Remove string operations from xstats Remy Horton
@ 2016-06-15 15:25         ` Remy Horton
  2016-06-15 15:25         ` [PATCH v5 2/7] drivers/net/ixgbe: " Remy Horton
                           ` (6 subsequent siblings)
  7 siblings, 0 replies; 71+ messages in thread
From: Remy Horton @ 2016-06-15 15:25 UTC (permalink / raw)
  To: dev, Thomas Monjalon, John McNamara

The current extended ethernet statistics fetching involve doing several
string operations, which causes performance issues if there are lots of
statistics and/or network interfaces. This patch changes the xstats
functions to instead use a numeric identifier rather than a string, and
adds the ability to retrieve identifier-to-string mappings.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 doc/guides/prog_guide/poll_mode_drv.rst | 25 +++++++--
 lib/librte_ether/rte_ethdev.c           | 93 ++++++++++++++++++++++++++++++---
 lib/librte_ether/rte_ethdev.h           | 41 +++++++++++++++
 lib/librte_ether/rte_ether_version.map  |  6 +++
 4 files changed, 153 insertions(+), 12 deletions(-)

diff --git a/doc/guides/prog_guide/poll_mode_drv.rst b/doc/guides/prog_guide/poll_mode_drv.rst
index 7698692..802fb8f 100644
--- a/doc/guides/prog_guide/poll_mode_drv.rst
+++ b/doc/guides/prog_guide/poll_mode_drv.rst
@@ -299,10 +299,27 @@ Extended Statistics API
 ~~~~~~~~~~~~~~~~~~~~~~~
 
 The extended statistics API allows each individual PMD to expose a unique set
-of statistics. The client of the API provides an array of
-``struct rte_eth_xstats`` type. Each ``struct rte_eth_xstats`` contains a
-string and value pair. The amount of xstats exposed, and position of the
-statistic in the array must remain constant during runtime.
+of statistics. Accessing these from application programs is done via two
+functions:
+
+* ``rte_eth_xstats_get``: Fills in an array of ``struct rte_eth_xstat``
+  with extended statistics.
+* ``rte_eth_xstats_get_names``: Fills in an array of
+  ``struct rte_eth_xstat_name`` with extended statistic name lookup
+  information.
+
+Each ``struct rte_eth_xstat`` contains an identifier and value pair, and
+each ``struct rte_eth_xstat_name`` contains an identifier and string pair.
+Each identifier within ``struct rte_eth_xstat`` must have a corresponding
+entry in ``struct rte_eth_xstat_name`` with a matching identifier. These
+identifiers, as well as the number of extended statistic exposed, must
+remain constant during runtime.
+
+Note that extended statistic identifiers are driver-specific, and hence
+might not be the same for different ports. Although it is expected that
+drivers will make the identifiers used within ``struct rte_eth_xstat`` and
+``struct rte_eth_xstat_name`` entries match the entries' array index, this
+property should not be relied on by applications for lookups.
 
 A naming scheme exists for the strings exposed to clients of the API. This is
 to allow scraping of the API for statistics of interest. The naming scheme uses
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index e148028..98e5efb 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -1502,6 +1502,85 @@ rte_eth_stats_reset(uint8_t port_id)
 	dev->data->rx_mbuf_alloc_failed = 0;
 }
 
+static int
+get_xstats_count(uint8_t port_id)
+{
+	struct rte_eth_dev *dev;
+	int count;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL);
+	dev = &rte_eth_devices[port_id];
+	if (dev->dev_ops->xstats_get_names != NULL) {
+		count = (*dev->dev_ops->xstats_get_names)(dev, NULL, 0);
+		if (count < 0)
+			return count;
+	} else
+		count = 0;
+	count += RTE_NB_STATS;
+	count += dev->data->nb_rx_queues * RTE_NB_RXQ_STATS;
+	count += dev->data->nb_tx_queues * RTE_NB_TXQ_STATS;
+	return count;
+}
+
+int
+rte_eth_xstats_get_names(uint8_t port_id,
+	struct rte_eth_xstat_name *xstats_names,
+	unsigned size)
+{
+	struct rte_eth_dev *dev;
+	int cnt_used_entries;
+	int cnt_expected_entries;
+	uint32_t idx, id_queue;
+
+	cnt_expected_entries = get_xstats_count(port_id);
+	if (xstats_names == NULL || cnt_expected_entries < 0 ||
+			(int)size < cnt_expected_entries)
+		return cnt_expected_entries;
+
+	/* port_id checked in get_xstats_count() */
+	dev = &rte_eth_devices[port_id];
+	if (dev->dev_ops->xstats_get_names != NULL) {
+		cnt_used_entries = (*dev->dev_ops->xstats_get_names)(
+			dev, xstats_names, size);
+		if (cnt_used_entries < 0)
+			return cnt_used_entries;
+	} else
+		/* Driver itself does not support extended stats, but
+		 * still have basic stats.
+		 */
+		cnt_used_entries = 0;
+
+	for (idx = 0; idx < RTE_NB_STATS; idx++) {
+		xstats_names[cnt_used_entries].id = cnt_used_entries;
+		snprintf(xstats_names[cnt_used_entries].name,
+			sizeof(xstats_names[0].name),
+			"%s", rte_stats_strings[idx].name);
+		cnt_used_entries++;
+	}
+	for (id_queue = 0; id_queue < dev->data->nb_rx_queues; id_queue++) {
+		for (idx = 0; idx < RTE_NB_RXQ_STATS; idx++) {
+			xstats_names[cnt_used_entries].id = cnt_used_entries;
+			snprintf(xstats_names[cnt_used_entries].name,
+				sizeof(xstats_names[0].name),
+				"rx_q%u%s",
+				id_queue, rte_rxq_stats_strings[idx].name);
+			cnt_used_entries++;
+		}
+
+	}
+	for (id_queue = 0; id_queue < dev->data->nb_tx_queues; id_queue++) {
+		for (idx = 0; idx < RTE_NB_TXQ_STATS; idx++) {
+			xstats_names[cnt_used_entries].id = cnt_used_entries;
+			snprintf(xstats_names[cnt_used_entries].name,
+				sizeof(xstats_names[0].name),
+				"tx_q%u%s",
+				id_queue, rte_txq_stats_strings[idx].name);
+			cnt_used_entries++;
+		}
+	}
+	return cnt_used_entries;
+}
+
 /* retrieve ethdev extended statistics */
 int
 rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
@@ -1546,8 +1625,8 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
 		stats_ptr = RTE_PTR_ADD(&eth_stats,
 					rte_stats_strings[i].offset);
 		val = *stats_ptr;
-		snprintf(xstats[count].name, sizeof(xstats[count].name),
-			"%s", rte_stats_strings[i].name);
+		xstats[count].name[0] = '\0';
+		xstats[count].id = count + xcount;
 		xstats[count++].value = val;
 	}
 
@@ -1558,9 +1637,8 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
 					rte_rxq_stats_strings[i].offset +
 					q * sizeof(uint64_t));
 			val = *stats_ptr;
-			snprintf(xstats[count].name, sizeof(xstats[count].name),
-				"rx_q%u_%s", q,
-				rte_rxq_stats_strings[i].name);
+			xstats[count].name[0] = '\0';
+			xstats[count].id = count + xcount;
 			xstats[count++].value = val;
 		}
 	}
@@ -1572,9 +1650,8 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
 					rte_txq_stats_strings[i].offset +
 					q * sizeof(uint64_t));
 			val = *stats_ptr;
-			snprintf(xstats[count].name, sizeof(xstats[count].name),
-				"tx_q%u_%s", q,
-				rte_txq_stats_strings[i].name);
+			xstats[count].name[0] = '\0';
+			xstats[count].id = count + xcount;
 			xstats[count++].value = val;
 		}
 	}
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 2757510..5de86b8 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -916,9 +916,21 @@ struct rte_eth_txq_info {
  */
 struct rte_eth_xstats {
 	char name[RTE_ETH_XSTATS_NAME_SIZE];
+	uint64_t id;
 	uint64_t value;
 };
 
+/**
+ * A name-key lookup element for extended statistics.
+ *
+ * This structure is used to map between names and ID numbers
+ * for extended ethernet statistics.
+ */
+struct rte_eth_xstat_name {
+	char name[RTE_ETH_XSTATS_NAME_SIZE];
+	uint64_t id;
+};
+
 #define ETH_DCB_NUM_TCS    8
 #define ETH_MAX_VMDQ_POOL  64
 
@@ -1054,6 +1066,10 @@ typedef int (*eth_xstats_get_t)(struct rte_eth_dev *dev,
 typedef void (*eth_xstats_reset_t)(struct rte_eth_dev *dev);
 /**< @internal Reset extended stats of an Ethernet device. */
 
+typedef int (*eth_xstats_get_names_t)(struct rte_eth_dev *dev,
+	struct rte_eth_xstat_name *xstats_names, unsigned size);
+/**< @internal Get names of extended stats of an Ethernet device. */
+
 typedef int (*eth_queue_stats_mapping_set_t)(struct rte_eth_dev *dev,
 					     uint16_t queue_id,
 					     uint8_t stat_idx,
@@ -1401,6 +1417,8 @@ struct eth_dev_ops {
 	eth_stats_reset_t          stats_reset;   /**< Reset generic device statistics. */
 	eth_xstats_get_t           xstats_get;    /**< Get extended device statistics. */
 	eth_xstats_reset_t         xstats_reset;  /**< Reset extended device statistics. */
+	eth_xstats_get_names_t     xstats_get_names;
+	/**< Get names of extended statistics. */
 	eth_queue_stats_mapping_set_t queue_stats_mapping_set;
 	/**< Configure per queue stat counter mapping. */
 	eth_dev_infos_get_t        dev_infos_get; /**< Get device info. */
@@ -2253,6 +2271,29 @@ int rte_eth_stats_get(uint8_t port_id, struct rte_eth_stats *stats);
 void rte_eth_stats_reset(uint8_t port_id);
 
 /**
+ * Retrieve names of extended statistics of an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param xstats_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 xstats_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.
+ *   - negative value on error (invalid port id)
+ */
+int rte_eth_xstats_get_names(uint8_t port_id,
+		struct rte_eth_xstat_name *xstats_names,
+		unsigned size);
+
+/**
  * Retrieve 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 214ecc7..722b4d6 100644
--- a/lib/librte_ether/rte_ether_version.map
+++ b/lib/librte_ether/rte_ether_version.map
@@ -132,3 +132,9 @@ DPDK_16.04 {
 	rte_eth_tx_buffer_set_err_callback;
 
 } DPDK_2.2;
+
+DPDK_16.07 {
+	global:
+
+	rte_eth_xstats_get_names;
+} DPDK_16.04;
-- 
2.5.5

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

* [PATCH v5 2/7] drivers/net/ixgbe: change xstats to use integer ids
  2016-06-15 15:25       ` [PATCH v5 0/7] Remove string operations from xstats Remy Horton
  2016-06-15 15:25         ` [PATCH v5 1/7] rte: change xstats to use integer ids Remy Horton
@ 2016-06-15 15:25         ` Remy Horton
  2016-06-15 15:25         ` [PATCH v5 3/7] drivers/net/e1000: " Remy Horton
                           ` (5 subsequent siblings)
  7 siblings, 0 replies; 71+ messages in thread
From: Remy Horton @ 2016-06-15 15:25 UTC (permalink / raw)
  To: dev, Thomas Monjalon

The current extended ethernet statistics fetching involve doing several
string operations, which causes performance issues if there are lots of
statistics and/or network interfaces. This patch changes the ixgbe driver
to use the new API that seperates name string and value queries.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 drivers/net/ixgbe/ixgbe_ethdev.c | 101 +++++++++++++++++++++++++++++++++------
 1 file changed, 86 insertions(+), 15 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index a2b170b..9e73492 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -179,6 +179,10 @@ static int ixgbevf_dev_xstats_get(struct rte_eth_dev *dev,
 				  struct rte_eth_xstats *xstats, unsigned n);
 static void ixgbe_dev_stats_reset(struct rte_eth_dev *dev);
 static void ixgbe_dev_xstats_reset(struct rte_eth_dev *dev);
+static int ixgbe_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
+	struct rte_eth_xstat_name *xstats_names, __rte_unused unsigned limit);
+static int ixgbevf_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
+	struct rte_eth_xstat_name *xstats_names, __rte_unused unsigned limit);
 static int ixgbe_dev_queue_stats_mapping_set(struct rte_eth_dev *eth_dev,
 					     uint16_t queue_id,
 					     uint8_t stat_idx,
@@ -466,6 +470,7 @@ static const struct eth_dev_ops ixgbe_eth_dev_ops = {
 	.xstats_get           = ixgbe_dev_xstats_get,
 	.stats_reset          = ixgbe_dev_stats_reset,
 	.xstats_reset         = ixgbe_dev_xstats_reset,
+	.xstats_get_names     = ixgbe_dev_xstats_get_names,
 	.queue_stats_mapping_set = ixgbe_dev_queue_stats_mapping_set,
 	.dev_infos_get        = ixgbe_dev_info_get,
 	.dev_supported_ptypes_get = ixgbe_dev_supported_ptypes_get,
@@ -555,6 +560,7 @@ static const struct eth_dev_ops ixgbevf_eth_dev_ops = {
 	.xstats_get           = ixgbevf_dev_xstats_get,
 	.stats_reset          = ixgbevf_dev_stats_reset,
 	.xstats_reset         = ixgbevf_dev_stats_reset,
+	.xstats_get_names     = ixgbevf_dev_xstats_get_names,
 	.dev_close            = ixgbevf_dev_close,
 	.allmulticast_enable  = ixgbevf_dev_allmulticast_enable,
 	.allmulticast_disable = ixgbevf_dev_allmulticast_disable,
@@ -685,6 +691,7 @@ static const struct rte_ixgbe_xstats_name_off rte_ixgbe_rxq_strings[] = {
 
 #define IXGBE_NB_RXQ_PRIO_STATS (sizeof(rte_ixgbe_rxq_strings) / \
 			   sizeof(rte_ixgbe_rxq_strings[0]))
+#define IXGBE_NB_RXQ_PRIO_VALUES 8
 
 static const struct rte_ixgbe_xstats_name_off rte_ixgbe_txq_strings[] = {
 	{"xon_packets", offsetof(struct ixgbe_hw_stats, pxontxc)},
@@ -695,6 +702,7 @@ static const struct rte_ixgbe_xstats_name_off rte_ixgbe_txq_strings[] = {
 
 #define IXGBE_NB_TXQ_PRIO_STATS (sizeof(rte_ixgbe_txq_strings) / \
 			   sizeof(rte_ixgbe_txq_strings[0]))
+#define IXGBE_NB_TXQ_PRIO_VALUES 8
 
 static const struct rte_ixgbe_xstats_name_off rte_ixgbevf_stats_strings[] = {
 	{"rx_multicast_packets", offsetof(struct ixgbevf_hw_stats, vfmprc)},
@@ -2695,8 +2703,75 @@ ixgbe_dev_stats_reset(struct rte_eth_dev *dev)
 /* This function calculates the number of xstats based on the current config */
 static unsigned
 ixgbe_xstats_calc_num(void) {
-	return IXGBE_NB_HW_STATS + (IXGBE_NB_RXQ_PRIO_STATS * 8) +
-		(IXGBE_NB_TXQ_PRIO_STATS * 8);
+	return IXGBE_NB_HW_STATS +
+		(IXGBE_NB_RXQ_PRIO_STATS * IXGBE_NB_RXQ_PRIO_VALUES) +
+		(IXGBE_NB_TXQ_PRIO_STATS * IXGBE_NB_TXQ_PRIO_VALUES);
+}
+
+static int ixgbe_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
+	struct rte_eth_xstat_name *xstats_names, __rte_unused unsigned limit)
+{
+	const unsigned cnt_stats = ixgbe_xstats_calc_num();
+	unsigned stat, i, count;
+
+	if (xstats_names != NULL) {
+		count = 0;
+
+		/* Note: limit >= cnt_stats checked upstream
+		 * in rte_eth_xstats_names()
+		 */
+
+		/* Extended stats from ixgbe_hw_stats */
+		for (i = 0; i < IXGBE_NB_HW_STATS; i++) {
+			xstats_names[count].id = count;
+			snprintf(xstats_names[count].name,
+				sizeof(xstats_names[count].name),
+				"%s",
+				rte_ixgbe_stats_strings[i].name);
+			count++;
+		}
+
+		/* RX Priority Stats */
+		for (stat = 0; stat < IXGBE_NB_RXQ_PRIO_STATS; stat++) {
+			for (i = 0; i < IXGBE_NB_RXQ_PRIO_VALUES; i++) {
+				xstats_names[count].id = count;
+				snprintf(xstats_names[count].name,
+					sizeof(xstats_names[count].name),
+					"rx_priority%u_%s", i,
+					rte_ixgbe_rxq_strings[stat].name);
+				count++;
+			}
+		}
+
+		/* TX Priority Stats */
+		for (stat = 0; stat < IXGBE_NB_TXQ_PRIO_STATS; stat++) {
+			for (i = 0; i < IXGBE_NB_TXQ_PRIO_VALUES; i++) {
+				xstats_names[count].id = count;
+				snprintf(xstats_names[count].name,
+					sizeof(xstats_names[count].name),
+					"tx_priority%u_%s", i,
+					rte_ixgbe_txq_strings[stat].name);
+				count++;
+			}
+		}
+	}
+	return cnt_stats;
+}
+
+static int ixgbevf_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
+	struct rte_eth_xstat_name *xstats_names, unsigned limit)
+{
+	unsigned i;
+
+	if (limit < IXGBEVF_NB_XSTATS && xstats_names != NULL)
+		return -ENOMEM;
+
+	if (xstats_names != NULL)
+		for (i = 0; i < IXGBEVF_NB_XSTATS; i++)
+			snprintf(xstats_names[i].name,
+				sizeof(xstats_names[i].name),
+				"%s", rte_ixgbevf_stats_strings[i].name);
+	return IXGBEVF_NB_XSTATS;
 }
 
 static int
@@ -2732,8 +2807,8 @@ ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 	/* Extended stats from ixgbe_hw_stats */
 	count = 0;
 	for (i = 0; i < IXGBE_NB_HW_STATS; i++) {
-		snprintf(xstats[count].name, sizeof(xstats[count].name), "%s",
-			 rte_ixgbe_stats_strings[i].name);
+		xstats[count].id = count;
+		xstats[count].name[0] = '\0';
 		xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
 				rte_ixgbe_stats_strings[i].offset);
 		count++;
@@ -2741,10 +2816,9 @@ ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 
 	/* RX Priority Stats */
 	for (stat = 0; stat < IXGBE_NB_RXQ_PRIO_STATS; stat++) {
-		for (i = 0; i < 8; i++) {
-			snprintf(xstats[count].name, sizeof(xstats[count].name),
-				 "rx_priority%u_%s", i,
-				 rte_ixgbe_rxq_strings[stat].name);
+		for (i = 0; i < IXGBE_NB_RXQ_PRIO_VALUES; i++) {
+			xstats[count].id = count;
+			xstats[count].name[0] = '\0';
 			xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
 					rte_ixgbe_rxq_strings[stat].offset +
 					(sizeof(uint64_t) * i));
@@ -2754,17 +2828,15 @@ ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 
 	/* TX Priority Stats */
 	for (stat = 0; stat < IXGBE_NB_TXQ_PRIO_STATS; stat++) {
-		for (i = 0; i < 8; i++) {
-			snprintf(xstats[count].name, sizeof(xstats[count].name),
-				 "tx_priority%u_%s", i,
-				 rte_ixgbe_txq_strings[stat].name);
+		for (i = 0; i < IXGBE_NB_TXQ_PRIO_VALUES; i++) {
+			xstats[count].id = count;
+			xstats[count].name[0] = '\0';
 			xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
 					rte_ixgbe_txq_strings[stat].offset +
 					(sizeof(uint64_t) * i));
 			count++;
 		}
 	}
-
 	return count;
 }
 
@@ -2829,8 +2901,7 @@ ixgbevf_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 
 	/* Extended stats */
 	for (i = 0; i < IXGBEVF_NB_XSTATS; i++) {
-		snprintf(xstats[i].name, sizeof(xstats[i].name),
-			 "%s", rte_ixgbevf_stats_strings[i].name);
+		xstats[i].id = i;
 		xstats[i].value = *(uint64_t *)(((char *)hw_stats) +
 			rte_ixgbevf_stats_strings[i].offset);
 	}
-- 
2.5.5

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

* [PATCH v5 3/7] drivers/net/e1000: change xstats to use integer ids
  2016-06-15 15:25       ` [PATCH v5 0/7] Remove string operations from xstats Remy Horton
  2016-06-15 15:25         ` [PATCH v5 1/7] rte: change xstats to use integer ids Remy Horton
  2016-06-15 15:25         ` [PATCH v5 2/7] drivers/net/ixgbe: " Remy Horton
@ 2016-06-15 15:25         ` Remy Horton
  2016-06-15 15:25         ` [PATCH v5 4/7] drivers/net/fm10k: " Remy Horton
                           ` (4 subsequent siblings)
  7 siblings, 0 replies; 71+ messages in thread
From: Remy Horton @ 2016-06-15 15:25 UTC (permalink / raw)
  To: dev, Thomas Monjalon

The current extended ethernet statistics fetching involve doing several
string operations, which causes performance issues if there are lots of
statistics and/or network interfaces. This patch changes the e1000 driver
to use the new API that seperates name string and value queries.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 drivers/net/e1000/igb_ethdev.c | 52 ++++++++++++++++++++++++++++++++++++++----
 1 file changed, 48 insertions(+), 4 deletions(-)

diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index f0921ee..dffa04f 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -100,6 +100,9 @@ static void eth_igb_stats_get(struct rte_eth_dev *dev,
 				struct rte_eth_stats *rte_stats);
 static int eth_igb_xstats_get(struct rte_eth_dev *dev,
 			      struct rte_eth_xstats *xstats, unsigned n);
+static int eth_igb_xstats_get_names(struct rte_eth_dev *dev,
+				    struct rte_eth_xstat_name *xstats_names,
+				    unsigned limit);
 static void eth_igb_stats_reset(struct rte_eth_dev *dev);
 static void eth_igb_xstats_reset(struct rte_eth_dev *dev);
 static void eth_igb_infos_get(struct rte_eth_dev *dev,
@@ -165,6 +168,9 @@ static void eth_igbvf_stats_get(struct rte_eth_dev *dev,
 				struct rte_eth_stats *rte_stats);
 static int eth_igbvf_xstats_get(struct rte_eth_dev *dev,
 				struct rte_eth_xstats *xstats, unsigned n);
+static int eth_igbvf_xstats_get_names(struct rte_eth_dev *dev,
+				      struct rte_eth_xstat_name *xstats_names,
+				      unsigned limit);
 static void eth_igbvf_stats_reset(struct rte_eth_dev *dev);
 static int igbvf_vlan_filter_set(struct rte_eth_dev *dev,
 		uint16_t vlan_id, int on);
@@ -324,6 +330,7 @@ static const struct eth_dev_ops eth_igb_ops = {
 	.link_update          = eth_igb_link_update,
 	.stats_get            = eth_igb_stats_get,
 	.xstats_get           = eth_igb_xstats_get,
+	.xstats_get_names     = eth_igb_xstats_get_names,
 	.stats_reset          = eth_igb_stats_reset,
 	.xstats_reset         = eth_igb_xstats_reset,
 	.dev_infos_get        = eth_igb_infos_get,
@@ -385,6 +392,7 @@ static const struct eth_dev_ops igbvf_eth_dev_ops = {
 	.link_update          = eth_igb_link_update,
 	.stats_get            = eth_igbvf_stats_get,
 	.xstats_get           = eth_igbvf_xstats_get,
+	.xstats_get_names     = eth_igbvf_xstats_get_names,
 	.stats_reset          = eth_igbvf_stats_reset,
 	.xstats_reset         = eth_igbvf_stats_reset,
 	.vlan_filter_set      = igbvf_vlan_filter_set,
@@ -1691,6 +1699,26 @@ eth_igb_xstats_reset(struct rte_eth_dev *dev)
 	memset(stats, 0, sizeof(*stats));
 }
 
+static int eth_igb_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
+	struct rte_eth_xstat_name *xstats_names,
+	__rte_unused unsigned limit)
+{
+	unsigned i;
+
+	if (xstats_names == NULL)
+		return IGB_NB_XSTATS;
+
+	/* Note: limit checked in rte_eth_xstats_names() */
+
+	for (i = 0; i < IGB_NB_XSTATS; i++) {
+		snprintf(xstats_names[i].name, sizeof(xstats_names[i].name),
+			 "%s", rte_igb_stats_strings[i].name);
+		xstats_names[i].id = i;
+	}
+
+	return IGB_NB_XSTATS;
+}
+
 static int
 eth_igb_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 		   unsigned n)
@@ -1713,8 +1741,8 @@ eth_igb_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 
 	/* Extended stats */
 	for (i = 0; i < IGB_NB_XSTATS; i++) {
-		snprintf(xstats[i].name, sizeof(xstats[i].name),
-			 "%s", rte_igb_stats_strings[i].name);
+		xstats[i].name[0] = '\0';
+		xstats[i].id = i;
 		xstats[i].value = *(uint64_t *)(((char *)hw_stats) +
 			rte_igb_stats_strings[i].offset);
 	}
@@ -1762,6 +1790,22 @@ igbvf_read_stats_registers(struct e1000_hw *hw, struct e1000_vf_stats *hw_stats)
 	    hw_stats->last_gotlbc, hw_stats->gotlbc);
 }
 
+static int eth_igbvf_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
+				     struct rte_eth_xstat_name *xstats_names,
+				     __rte_unused unsigned limit)
+{
+	unsigned i;
+
+	if (xstats_names != NULL)
+		for (i = 0; i < IGBVF_NB_XSTATS; i++) {
+			snprintf(xstats_names[i].name,
+				sizeof(xstats_names[i].name), "%s",
+				rte_igbvf_stats_strings[i].name);
+			xstats_names[i].id = i;
+		}
+	return IGBVF_NB_XSTATS;
+}
+
 static int
 eth_igbvf_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 		     unsigned n)
@@ -1780,8 +1824,8 @@ eth_igbvf_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 		return 0;
 
 	for (i = 0; i < IGBVF_NB_XSTATS; i++) {
-		snprintf(xstats[i].name, sizeof(xstats[i].name), "%s",
-			 rte_igbvf_stats_strings[i].name);
+		xstats[i].name[0] = '\0';
+		xstats[i].id = i;
 		xstats[i].value = *(uint64_t *)(((char *)hw_stats) +
 			rte_igbvf_stats_strings[i].offset);
 	}
-- 
2.5.5

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

* [PATCH v5 4/7] drivers/net/fm10k: change xstats to use integer ids
  2016-06-15 15:25       ` [PATCH v5 0/7] Remove string operations from xstats Remy Horton
                           ` (2 preceding siblings ...)
  2016-06-15 15:25         ` [PATCH v5 3/7] drivers/net/e1000: " Remy Horton
@ 2016-06-15 15:25         ` Remy Horton
  2016-06-15 15:25         ` [PATCH v5 5/7] drivers/net/i40e: " Remy Horton
                           ` (3 subsequent siblings)
  7 siblings, 0 replies; 71+ messages in thread
From: Remy Horton @ 2016-06-15 15:25 UTC (permalink / raw)
  To: dev, Thomas Monjalon

The current extended ethernet statistics fetching involve doing several
string operations, which causes performance issues if there are lots of
statistics and/or network interfaces. This patch changes the fm10k driver
to use the new API that seperates name string and value queries.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 drivers/net/fm10k/fm10k_ethdev.c | 55 +++++++++++++++++++++++++++++++++-------
 1 file changed, 46 insertions(+), 9 deletions(-)

diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c
index c2d377f..e07c1ec 100644
--- a/drivers/net/fm10k/fm10k_ethdev.c
+++ b/drivers/net/fm10k/fm10k_ethdev.c
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2013-2015 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2013-2016 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -1256,6 +1256,47 @@ fm10k_link_update(struct rte_eth_dev *dev,
 	return 0;
 }
 
+static int fm10k_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
+	struct rte_eth_xstat_name *xstats_names, __rte_unused unsigned limit)
+{
+	unsigned i, q;
+	unsigned count = 0;
+
+	if (xstats_names != NULL) {
+		/* Note: limit checked in rte_eth_xstats_names() */
+
+		/* Global stats */
+		for (i = 0; i < FM10K_NB_HW_XSTATS; i++) {
+			snprintf(xstats_names[count].name,
+				sizeof(xstats_names[count].name),
+				"%s", fm10k_hw_stats_strings[count].name);
+			xstats_names[count].id = count;
+			count++;
+		}
+
+		/* PF queue stats */
+		for (q = 0; q < FM10K_MAX_QUEUES_PF; q++) {
+			for (i = 0; i < FM10K_NB_RX_Q_XSTATS; i++) {
+				snprintf(xstats_names[count].name,
+					sizeof(xstats_names[count].name),
+					"rx_q%u_%s", q,
+					fm10k_hw_stats_rx_q_strings[i].name);
+				xstats_names[count].id = count;
+				count++;
+			}
+			for (i = 0; i < FM10K_NB_TX_Q_XSTATS; i++) {
+				snprintf(xstats_names[count].name,
+					sizeof(xstats_names[count].name),
+					"tx_q%u_%s", q,
+					fm10k_hw_stats_tx_q_strings[i].name);
+				xstats_names[count].id = count;
+				count++;
+			}
+		}
+	}
+	return FM10K_NB_XSTATS;
+}
+
 static int
 fm10k_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 		 unsigned n)
@@ -1269,8 +1310,7 @@ fm10k_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 
 	/* Global stats */
 	for (i = 0; i < FM10K_NB_HW_XSTATS; i++) {
-		snprintf(xstats[count].name, sizeof(xstats[count].name),
-			 "%s", fm10k_hw_stats_strings[count].name);
+		xstats[count].name[0] = '\0';
 		xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
 			fm10k_hw_stats_strings[count].offset);
 		count++;
@@ -1279,18 +1319,14 @@ fm10k_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 	/* PF queue stats */
 	for (q = 0; q < FM10K_MAX_QUEUES_PF; q++) {
 		for (i = 0; i < FM10K_NB_RX_Q_XSTATS; i++) {
-			snprintf(xstats[count].name, sizeof(xstats[count].name),
-				 "rx_q%u_%s", q,
-				 fm10k_hw_stats_rx_q_strings[i].name);
+			xstats[count].name[0] = '\0';
 			xstats[count].value =
 				*(uint64_t *)(((char *)&hw_stats->q[q]) +
 				fm10k_hw_stats_rx_q_strings[i].offset);
 			count++;
 		}
 		for (i = 0; i < FM10K_NB_TX_Q_XSTATS; i++) {
-			snprintf(xstats[count].name, sizeof(xstats[count].name),
-				 "tx_q%u_%s", q,
-				 fm10k_hw_stats_tx_q_strings[i].name);
+			xstats[count].name[0] = '\0';
 			xstats[count].value =
 				*(uint64_t *)(((char *)&hw_stats->q[q]) +
 				fm10k_hw_stats_tx_q_strings[i].offset);
@@ -2629,6 +2665,7 @@ static const struct eth_dev_ops fm10k_eth_dev_ops = {
 	.allmulticast_disable   = fm10k_dev_allmulticast_disable,
 	.stats_get		= fm10k_stats_get,
 	.xstats_get		= fm10k_xstats_get,
+	.xstats_get_names	= fm10k_xstats_get_names,
 	.stats_reset		= fm10k_stats_reset,
 	.xstats_reset		= fm10k_stats_reset,
 	.link_update		= fm10k_link_update,
-- 
2.5.5

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

* [PATCH v5 5/7] drivers/net/i40e: change xstats to use integer ids
  2016-06-15 15:25       ` [PATCH v5 0/7] Remove string operations from xstats Remy Horton
                           ` (3 preceding siblings ...)
  2016-06-15 15:25         ` [PATCH v5 4/7] drivers/net/fm10k: " Remy Horton
@ 2016-06-15 15:25         ` Remy Horton
  2016-06-15 15:25         ` [PATCH v5 6/7] drivers/net/virtio: " Remy Horton
                           ` (2 subsequent siblings)
  7 siblings, 0 replies; 71+ messages in thread
From: Remy Horton @ 2016-06-15 15:25 UTC (permalink / raw)
  To: dev, Thomas Monjalon

The current extended ethernet statistics fetching involve doing several
string operations, which causes performance issues if there are lots of
statistics and/or network interfaces. This patch changes the i40e driver
to use the new API that seperates name string and value queries.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 drivers/net/i40e/i40e_ethdev.c    | 82 ++++++++++++++++++++++++++++++++-------
 drivers/net/i40e/i40e_ethdev_vf.c | 26 +++++++++++--
 2 files changed, 91 insertions(+), 17 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 24777d5..d712bbe 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -306,6 +306,9 @@ static void i40e_dev_stats_get(struct rte_eth_dev *dev,
 			       struct rte_eth_stats *stats);
 static int i40e_dev_xstats_get(struct rte_eth_dev *dev,
 			       struct rte_eth_xstats *xstats, unsigned n);
+static int i40e_dev_xstats_get_names(struct rte_eth_dev *dev,
+				     struct rte_eth_xstat_name *xstats_names,
+				     unsigned limit);
 static void i40e_dev_stats_reset(struct rte_eth_dev *dev);
 static int i40e_dev_queue_stats_mapping_set(struct rte_eth_dev *dev,
 					    uint16_t queue_id,
@@ -467,6 +470,7 @@ static const struct eth_dev_ops i40e_eth_dev_ops = {
 	.link_update                  = i40e_dev_link_update,
 	.stats_get                    = i40e_dev_stats_get,
 	.xstats_get                   = i40e_dev_xstats_get,
+	.xstats_get_names             = i40e_dev_xstats_get_names,
 	.stats_reset                  = i40e_dev_stats_reset,
 	.xstats_reset                 = i40e_dev_stats_reset,
 	.queue_stats_mapping_set      = i40e_dev_queue_stats_mapping_set,
@@ -2205,6 +2209,60 @@ i40e_xstats_calc_num(void)
 		(I40E_NB_TXQ_PRIO_XSTATS * 8);
 }
 
+static int i40e_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
+				     struct rte_eth_xstat_name *xstats_names,
+				     __rte_unused unsigned limit)
+{
+	unsigned count = 0;
+	unsigned i, prio;
+
+	if (xstats_names == NULL)
+		return i40e_xstats_calc_num();
+
+	/* Note: limit checked in rte_eth_xstats_names() */
+
+	/* Get stats from i40e_eth_stats struct */
+	for (i = 0; i < I40E_NB_ETH_XSTATS; i++) {
+		snprintf(xstats_names[count].name,
+			 sizeof(xstats_names[count].name),
+			 "%s", rte_i40e_stats_strings[i].name);
+		xstats_names[count].id = count;
+		count++;
+	}
+
+	/* Get individiual stats from i40e_hw_port struct */
+	for (i = 0; i < I40E_NB_HW_PORT_XSTATS; i++) {
+		snprintf(xstats_names[count].name,
+			sizeof(xstats_names[count].name),
+			 "%s", rte_i40e_hw_port_strings[i].name);
+		xstats_names[count].id = count;
+		count++;
+	}
+
+	for (i = 0; i < I40E_NB_RXQ_PRIO_XSTATS; i++) {
+		for (prio = 0; prio < 8; prio++) {
+			snprintf(xstats_names[count].name,
+				 sizeof(xstats_names[count].name),
+				 "rx_priority%u_%s", prio,
+				 rte_i40e_rxq_prio_strings[i].name);
+			xstats_names[count].id = count;
+			count++;
+		}
+	}
+
+	for (i = 0; i < I40E_NB_TXQ_PRIO_XSTATS; i++) {
+		for (prio = 0; prio < 8; prio++) {
+			snprintf(xstats_names[count].name,
+				 sizeof(xstats_names[count].name),
+				 "tx_priority%u_%s", prio,
+				 rte_i40e_txq_prio_strings[i].name);
+			xstats_names[count].id = count;
+			count++;
+		}
+	}
+	return count;
+}
+
 static int
 i40e_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 		    unsigned n)
@@ -2227,8 +2285,8 @@ i40e_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 
 	/* Get stats from i40e_eth_stats struct */
 	for (i = 0; i < I40E_NB_ETH_XSTATS; i++) {
-		snprintf(xstats[count].name, sizeof(xstats[count].name),
-			 "%s", rte_i40e_stats_strings[i].name);
+		xstats[count].name[0] = '\0';
+		xstats[count].id = count;
 		xstats[count].value = *(uint64_t *)(((char *)&hw_stats->eth) +
 			rte_i40e_stats_strings[i].offset);
 		count++;
@@ -2236,19 +2294,17 @@ i40e_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 
 	/* Get individiual stats from i40e_hw_port struct */
 	for (i = 0; i < I40E_NB_HW_PORT_XSTATS; i++) {
-		snprintf(xstats[count].name, sizeof(xstats[count].name),
-			 "%s", rte_i40e_hw_port_strings[i].name);
+		xstats[count].name[0] = '\0';
+		xstats[count].id = count;
 		xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
-				rte_i40e_hw_port_strings[i].offset);
+			rte_i40e_hw_port_strings[i].offset);
 		count++;
 	}
 
 	for (i = 0; i < I40E_NB_RXQ_PRIO_XSTATS; i++) {
 		for (prio = 0; prio < 8; prio++) {
-			snprintf(xstats[count].name,
-				 sizeof(xstats[count].name),
-				 "rx_priority%u_%s", prio,
-				 rte_i40e_rxq_prio_strings[i].name);
+			xstats[count].name[0] = '\0';
+			xstats[count].id = count;
 			xstats[count].value =
 				*(uint64_t *)(((char *)hw_stats) +
 				rte_i40e_rxq_prio_strings[i].offset +
@@ -2259,10 +2315,8 @@ i40e_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 
 	for (i = 0; i < I40E_NB_TXQ_PRIO_XSTATS; i++) {
 		for (prio = 0; prio < 8; prio++) {
-			snprintf(xstats[count].name,
-				 sizeof(xstats[count].name),
-				 "tx_priority%u_%s", prio,
-				 rte_i40e_txq_prio_strings[i].name);
+			xstats[count].name[0] = '\0';
+			xstats[count].id = count;
 			xstats[count].value =
 				*(uint64_t *)(((char *)hw_stats) +
 				rte_i40e_txq_prio_strings[i].offset +
diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
index 90682ac..4c5e45e 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -112,6 +112,9 @@ static void i40evf_dev_stats_get(struct rte_eth_dev *dev,
 				struct rte_eth_stats *stats);
 static int i40evf_dev_xstats_get(struct rte_eth_dev *dev,
 				 struct rte_eth_xstats *xstats, unsigned n);
+static int i40evf_dev_xstats_get_names(struct rte_eth_dev *dev,
+				       struct rte_eth_xstat_name *xstats_names,
+				       unsigned limit);
 static void i40evf_dev_xstats_reset(struct rte_eth_dev *dev);
 static int i40evf_vlan_filter_set(struct rte_eth_dev *dev,
 				  uint16_t vlan_id, int on);
@@ -196,6 +199,7 @@ static const struct eth_dev_ops i40evf_eth_dev_ops = {
 	.link_update          = i40evf_dev_link_update,
 	.stats_get            = i40evf_dev_stats_get,
 	.xstats_get           = i40evf_dev_xstats_get,
+	.xstats_get_names     = i40evf_dev_xstats_get_names,
 	.xstats_reset         = i40evf_dev_xstats_reset,
 	.dev_close            = i40evf_dev_close,
 	.dev_infos_get        = i40evf_dev_info_get,
@@ -984,6 +988,22 @@ i40evf_dev_xstats_reset(struct rte_eth_dev *dev)
 	vf->vsi.eth_stats_offset = vf->vsi.eth_stats;
 }
 
+static int i40evf_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
+				      struct rte_eth_xstat_name *xstats_names,
+				      __rte_unused unsigned limit)
+{
+	unsigned i;
+
+	if (xstats_names != NULL)
+		for (i = 0; i < I40EVF_NB_XSTATS; i++) {
+			snprintf(xstats_names[i].name,
+				sizeof(xstats_names[i].name),
+				"%s", rte_i40evf_stats_strings[i].name);
+			xstats_names[i].id = i;
+		}
+	return I40EVF_NB_XSTATS;
+}
+
 static int i40evf_dev_xstats_get(struct rte_eth_dev *dev,
 				 struct rte_eth_xstats *xstats, unsigned n)
 {
@@ -1003,8 +1023,8 @@ static int i40evf_dev_xstats_get(struct rte_eth_dev *dev,
 
 	/* loop over xstats array and values from pstats */
 	for (i = 0; i < I40EVF_NB_XSTATS; i++) {
-		snprintf(xstats[i].name, sizeof(xstats[i].name),
-			 "%s", rte_i40evf_stats_strings[i].name);
+		xstats[i].name[0] = '\0';
+		xstats[i].id = i;
 		xstats[i].value = *(uint64_t *)(((char *)pstats) +
 			rte_i40evf_stats_strings[i].offset);
 	}
-- 
2.5.5

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

* [PATCH v5 6/7] drivers/net/virtio: change xstats to use integer ids
  2016-06-15 15:25       ` [PATCH v5 0/7] Remove string operations from xstats Remy Horton
                           ` (4 preceding siblings ...)
  2016-06-15 15:25         ` [PATCH v5 5/7] drivers/net/i40e: " Remy Horton
@ 2016-06-15 15:25         ` Remy Horton
  2016-06-20 10:43           ` Yuanhan Liu
  2016-06-15 15:25         ` [PATCH v5 7/7] rte: change xstats usage to new API Remy Horton
  2016-06-16 16:02         ` [PATCH v5 0/7] Remove string operations from xstats Thomas Monjalon
  7 siblings, 1 reply; 71+ messages in thread
From: Remy Horton @ 2016-06-15 15:25 UTC (permalink / raw)
  To: dev, Thomas Monjalon

The current extended ethernet statistics fetching involve doing several
string operations, which causes performance issues if there are lots of
statistics and/or network interfaces. This patch changes the virtio driver
to use the new API that seperates name string and value queries.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 drivers/net/virtio/virtio_ethdev.c | 62 +++++++++++++++++++++++++++++++++-----
 1 file changed, 55 insertions(+), 7 deletions(-)

diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c
index c3fb628..83df025 100644
--- a/drivers/net/virtio/virtio_ethdev.c
+++ b/drivers/net/virtio/virtio_ethdev.c
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -80,6 +80,9 @@ static void virtio_dev_stats_get(struct rte_eth_dev *dev,
 				 struct rte_eth_stats *stats);
 static int virtio_dev_xstats_get(struct rte_eth_dev *dev,
 				 struct rte_eth_xstats *xstats, unsigned n);
+static int virtio_dev_xstats_get_names(struct rte_eth_dev *dev,
+				       struct rte_eth_xstat_name *xstats_names,
+				       unsigned limit);
 static void virtio_dev_stats_reset(struct rte_eth_dev *dev);
 static void virtio_dev_free_mbufs(struct rte_eth_dev *dev);
 static int virtio_vlan_filter_set(struct rte_eth_dev *dev,
@@ -615,6 +618,7 @@ static const struct eth_dev_ops virtio_eth_dev_ops = {
 	.dev_infos_get           = virtio_dev_info_get,
 	.stats_get               = virtio_dev_stats_get,
 	.xstats_get              = virtio_dev_xstats_get,
+	.xstats_get_names        = virtio_dev_xstats_get_names,
 	.stats_reset             = virtio_dev_stats_reset,
 	.xstats_reset            = virtio_dev_stats_reset,
 	.link_update             = virtio_dev_link_update,
@@ -708,6 +712,52 @@ virtio_update_stats(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
 	stats->rx_nombuf = dev->data->rx_mbuf_alloc_failed;
 }
 
+static int virtio_dev_xstats_get_names(struct rte_eth_dev *dev,
+				       struct rte_eth_xstat_name *xstats_names,
+				       __rte_unused unsigned limit)
+{
+	unsigned i;
+	unsigned count = 0;
+	unsigned t;
+
+	unsigned nstats = dev->data->nb_tx_queues * VIRTIO_NB_Q_XSTATS +
+		dev->data->nb_rx_queues * VIRTIO_NB_Q_XSTATS;
+
+	if (xstats_names == NULL) {
+		/* Note: limit checked in rte_eth_xstats_names() */
+
+		for (i = 0; i < dev->data->nb_rx_queues; i++) {
+			struct virtqueue *rxvq = dev->data->rx_queues[i];
+			if (rxvq == NULL)
+				continue;
+			for (t = 0; t < VIRTIO_NB_Q_XSTATS; t++) {
+				snprintf(xstats_names[count].name,
+					sizeof(xstats_names[count].name),
+					"rx_q%u_%s", i,
+					rte_virtio_q_stat_strings[t].name);
+				xstats_names[count].id = count;
+				count++;
+			}
+		}
+
+		for (i = 0; i < dev->data->nb_tx_queues; i++) {
+			struct virtqueue *txvq = dev->data->tx_queues[i];
+			if (txvq == NULL)
+				continue;
+			for (t = 0; t < VIRTIO_NB_Q_XSTATS; t++) {
+				snprintf(xstats_names[count].name,
+					sizeof(xstats_names[count].name),
+					"tx_q%u_%s", i,
+					rte_virtio_q_stat_strings[t].name);
+				xstats_names[count].id = count;
+				count++;
+			}
+		}
+		return count;
+	}
+	return nstats;
+}
+
 static int
 virtio_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 		      unsigned n)
@@ -730,9 +780,8 @@ virtio_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 		unsigned t;
 
 		for (t = 0; t < VIRTIO_NB_Q_XSTATS; t++) {
-			snprintf(xstats[count].name, sizeof(xstats[count].name),
-				 "rx_q%u_%s", i,
-				 rte_virtio_q_stat_strings[t].name);
+			xstats[count].name[0] = '\0';
+			xstats[count].id = count;
 			xstats[count].value = *(uint64_t *)(((char *)rxvq) +
 				rte_virtio_q_stat_strings[t].offset);
 			count++;
@@ -748,9 +797,8 @@ virtio_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 		unsigned t;
 
 		for (t = 0; t < VIRTIO_NB_Q_XSTATS; t++) {
-			snprintf(xstats[count].name, sizeof(xstats[count].name),
-				 "tx_q%u_%s", i,
-				 rte_virtio_q_stat_strings[t].name);
+			xstats[count].name[0] = '\0';
+			xstats[count].id = count;
 			xstats[count].value = *(uint64_t *)(((char *)txvq) +
 				rte_virtio_q_stat_strings[t].offset);
 			count++;
-- 
2.5.5

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

* [PATCH v5 7/7] rte: change xstats usage to new API
  2016-06-15 15:25       ` [PATCH v5 0/7] Remove string operations from xstats Remy Horton
                           ` (5 preceding siblings ...)
  2016-06-15 15:25         ` [PATCH v5 6/7] drivers/net/virtio: " Remy Horton
@ 2016-06-15 15:25         ` Remy Horton
  2016-06-16 16:02         ` [PATCH v5 0/7] Remove string operations from xstats Thomas Monjalon
  7 siblings, 0 replies; 71+ messages in thread
From: Remy Horton @ 2016-06-15 15:25 UTC (permalink / raw)
  To: dev, Thomas Monjalon

The current extended ethernet statistics fetching involve doing several
string operations, which causes performance issues if there are lots of
statistics and/or network interfaces. This patch changes the test-pmd
and proc_info applications to use the new xstats API, and removes
deprecated code associated with the old API.

Signed-off-by: Remy Horton <remy.horton@intel.com>
---
 app/proc_info/main.c               | 29 +++++++++++++++++---
 app/test-pmd/config.c              | 54 +++++++++++++++++++++++++++++---------
 drivers/net/e1000/igb_ethdev.c     | 10 +++----
 drivers/net/fm10k/fm10k_ethdev.c   |  5 +---
 drivers/net/i40e/i40e_ethdev.c     |  8 ++----
 drivers/net/i40e/i40e_ethdev_vf.c  |  5 ++--
 drivers/net/ixgbe/ixgbe_ethdev.c   | 11 +++-----
 drivers/net/virtio/virtio_ethdev.c |  6 ++---
 lib/librte_ether/rte_ethdev.c      |  5 +---
 lib/librte_ether/rte_ethdev.h      |  7 +++--
 10 files changed, 85 insertions(+), 55 deletions(-)

diff --git a/app/proc_info/main.c b/app/proc_info/main.c
index 5f83092..f2063fa 100644
--- a/app/proc_info/main.c
+++ b/app/proc_info/main.c
@@ -1,7 +1,7 @@
 /*
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -243,11 +243,13 @@ nic_stats_clear(uint8_t port_id)
 static void
 nic_xstats_display(uint8_t port_id)
 {
-	struct rte_eth_xstats *xstats;
+	struct rte_eth_xstat_name *xstats_names;
+	struct rte_eth_xstat *xstats;
 	int len, ret, i;
+	int idx_name;
 	static const char *nic_stats_border = "########################";
 
-	len = rte_eth_xstats_get(port_id, NULL, 0);
+	len = rte_eth_xstats_get_names(port_id, NULL, 0);
 	if (len < 0) {
 		printf("Cannot get xstats count\n");
 		return;
@@ -258,6 +260,18 @@ nic_xstats_display(uint8_t port_id)
 		return;
 	}
 
+	xstats_names = malloc(sizeof(struct rte_eth_xstat_name) * len);
+	if (xstats_names == NULL) {
+		printf("Cannot allocate memory for xstat names\n");
+		free(xstats);
+		return;
+	}
+	if (len != rte_eth_xstats_get_names(
+			port_id, xstats_names, len)) {
+		printf("Cannot get xstat names\n");
+		return;
+	}
+
 	printf("###### NIC extended statistics for port %-2d #########\n",
 			   port_id);
 	printf("%s############################\n",
@@ -270,11 +284,18 @@ nic_xstats_display(uint8_t port_id)
 	}
 
 	for (i = 0; i < len; i++)
-		printf("%s: %"PRIu64"\n", xstats[i].name, xstats[i].value);
+		for (idx_name = 0; idx_name < len; idx_name++)
+			if (xstats_names[idx_name].id == xstats[i].id) {
+				printf("%s: %"PRIu64"\n",
+					xstats_names[idx_name].name,
+					xstats[i].value);
+				break;
+			}
 
 	printf("%s############################\n",
 			   nic_stats_border);
 	free(xstats);
+	free(xstats_names);
 }
 
 static void
diff --git a/app/test-pmd/config.c b/app/test-pmd/config.c
index 1c552e4..8ddec07 100644
--- a/app/test-pmd/config.c
+++ b/app/test-pmd/config.c
@@ -1,7 +1,7 @@
 /*-
  *   BSD LICENSE
  *
- *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ *   Copyright(c) 2010-2016 Intel Corporation. All rights reserved.
  *   All rights reserved.
  *
  *   Redistribution and use in source and binary forms, with or without
@@ -232,29 +232,57 @@ nic_stats_clear(portid_t port_id)
 void
 nic_xstats_display(portid_t port_id)
 {
-	struct rte_eth_xstats *xstats;
-	int len, ret, i;
+	struct rte_eth_xstat *xstats;
+	int cnt_xstats, idx_xstat, idx_name;
+	struct rte_eth_xstat_name *xstats_names;
 
 	printf("###### NIC extended statistics for port %-2d\n", port_id);
+	if (!rte_eth_dev_is_valid_port(port_id)) {
+		printf("Error: Invalid port number %i\n", port_id);
+		return;
+	}
+
+	/* Get count */
+	cnt_xstats = rte_eth_xstats_get_names(port_id, NULL, 0);
+	if (cnt_xstats  < 0) {
+		printf("Error: Cannot get count of xstats\n");
+		return;
+	}
 
-	len = rte_eth_xstats_get(port_id, NULL, 0);
-	if (len < 0) {
-		printf("Cannot get xstats count\n");
+	/* Get id-name lookup table */
+	xstats_names = malloc(sizeof(struct rte_eth_xstat_name) * cnt_xstats);
+	if (xstats_names == NULL) {
+		printf("Cannot allocate memory for xstats lookup\n");
 		return;
 	}
-	xstats = malloc(sizeof(xstats[0]) * len);
+	if (cnt_xstats != rte_eth_xstats_get_names(
+			port_id, xstats_names, cnt_xstats)) {
+		printf("Error: Cannot get xstats lookup\n");
+		return;
+	}
+
+	/* Get stats themselves */
+	xstats = malloc(sizeof(struct rte_eth_xstat) * cnt_xstats);
 	if (xstats == NULL) {
 		printf("Cannot allocate memory for xstats\n");
+		free(xstats_names);
 		return;
 	}
-	ret = rte_eth_xstats_get(port_id, xstats, len);
-	if (ret < 0 || ret > len) {
-		printf("Cannot get xstats\n");
-		free(xstats);
+	if (cnt_xstats != rte_eth_xstats_get(port_id, xstats, cnt_xstats)) {
+		printf("Error: Unable to get xstats\n");
 		return;
 	}
-	for (i = 0; i < len; i++)
-		printf("%s: %"PRIu64"\n", xstats[i].name, xstats[i].value);
+
+	/* Display xstats */
+	for (idx_xstat = 0; idx_xstat < cnt_xstats; idx_xstat++)
+		for (idx_name = 0; idx_name < cnt_xstats; idx_name++)
+			if (xstats_names[idx_name].id == xstats[idx_xstat].id) {
+				printf("%s: %"PRIu64"\n",
+					xstats_names[idx_name].name,
+					xstats[idx_xstat].value);
+				break;
+			}
+	free(xstats_names);
 	free(xstats);
 }
 
diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index dffa04f..b822992 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -99,7 +99,7 @@ static int  eth_igb_link_update(struct rte_eth_dev *dev,
 static void eth_igb_stats_get(struct rte_eth_dev *dev,
 				struct rte_eth_stats *rte_stats);
 static int eth_igb_xstats_get(struct rte_eth_dev *dev,
-			      struct rte_eth_xstats *xstats, unsigned n);
+			      struct rte_eth_xstat *xstats, unsigned n);
 static int eth_igb_xstats_get_names(struct rte_eth_dev *dev,
 				    struct rte_eth_xstat_name *xstats_names,
 				    unsigned limit);
@@ -167,7 +167,7 @@ static int eth_igbvf_link_update(struct e1000_hw *hw);
 static void eth_igbvf_stats_get(struct rte_eth_dev *dev,
 				struct rte_eth_stats *rte_stats);
 static int eth_igbvf_xstats_get(struct rte_eth_dev *dev,
-				struct rte_eth_xstats *xstats, unsigned n);
+				struct rte_eth_xstat *xstats, unsigned n);
 static int eth_igbvf_xstats_get_names(struct rte_eth_dev *dev,
 				      struct rte_eth_xstat_name *xstats_names,
 				      unsigned limit);
@@ -1720,7 +1720,7 @@ static int eth_igb_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 }
 
 static int
-eth_igb_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
+eth_igb_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
 		   unsigned n)
 {
 	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
@@ -1741,7 +1741,6 @@ eth_igb_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 
 	/* Extended stats */
 	for (i = 0; i < IGB_NB_XSTATS; i++) {
-		xstats[i].name[0] = '\0';
 		xstats[i].id = i;
 		xstats[i].value = *(uint64_t *)(((char *)hw_stats) +
 			rte_igb_stats_strings[i].offset);
@@ -1807,7 +1806,7 @@ static int eth_igbvf_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 }
 
 static int
-eth_igbvf_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
+eth_igbvf_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
 		     unsigned n)
 {
 	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
@@ -1824,7 +1823,6 @@ eth_igbvf_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 		return 0;
 
 	for (i = 0; i < IGBVF_NB_XSTATS; i++) {
-		xstats[i].name[0] = '\0';
 		xstats[i].id = i;
 		xstats[i].value = *(uint64_t *)(((char *)hw_stats) +
 			rte_igbvf_stats_strings[i].offset);
diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c
index e07c1ec..ce053b0 100644
--- a/drivers/net/fm10k/fm10k_ethdev.c
+++ b/drivers/net/fm10k/fm10k_ethdev.c
@@ -1298,7 +1298,7 @@ static int fm10k_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 }
 
 static int
-fm10k_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
+fm10k_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
 		 unsigned n)
 {
 	struct fm10k_hw_stats *hw_stats =
@@ -1310,7 +1310,6 @@ fm10k_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 
 	/* Global stats */
 	for (i = 0; i < FM10K_NB_HW_XSTATS; i++) {
-		xstats[count].name[0] = '\0';
 		xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
 			fm10k_hw_stats_strings[count].offset);
 		count++;
@@ -1319,14 +1318,12 @@ fm10k_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 	/* PF queue stats */
 	for (q = 0; q < FM10K_MAX_QUEUES_PF; q++) {
 		for (i = 0; i < FM10K_NB_RX_Q_XSTATS; i++) {
-			xstats[count].name[0] = '\0';
 			xstats[count].value =
 				*(uint64_t *)(((char *)&hw_stats->q[q]) +
 				fm10k_hw_stats_rx_q_strings[i].offset);
 			count++;
 		}
 		for (i = 0; i < FM10K_NB_TX_Q_XSTATS; i++) {
-			xstats[count].name[0] = '\0';
 			xstats[count].value =
 				*(uint64_t *)(((char *)&hw_stats->q[q]) +
 				fm10k_hw_stats_tx_q_strings[i].offset);
diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index d712bbe..f94ad87 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -305,7 +305,7 @@ static int i40e_dev_set_link_down(struct rte_eth_dev *dev);
 static void i40e_dev_stats_get(struct rte_eth_dev *dev,
 			       struct rte_eth_stats *stats);
 static int i40e_dev_xstats_get(struct rte_eth_dev *dev,
-			       struct rte_eth_xstats *xstats, unsigned n);
+			       struct rte_eth_xstat *xstats, unsigned n);
 static int i40e_dev_xstats_get_names(struct rte_eth_dev *dev,
 				     struct rte_eth_xstat_name *xstats_names,
 				     unsigned limit);
@@ -2264,7 +2264,7 @@ static int i40e_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 }
 
 static int
-i40e_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
+i40e_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
 		    unsigned n)
 {
 	struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
@@ -2285,7 +2285,6 @@ i40e_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 
 	/* Get stats from i40e_eth_stats struct */
 	for (i = 0; i < I40E_NB_ETH_XSTATS; i++) {
-		xstats[count].name[0] = '\0';
 		xstats[count].id = count;
 		xstats[count].value = *(uint64_t *)(((char *)&hw_stats->eth) +
 			rte_i40e_stats_strings[i].offset);
@@ -2294,7 +2293,6 @@ i40e_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 
 	/* Get individiual stats from i40e_hw_port struct */
 	for (i = 0; i < I40E_NB_HW_PORT_XSTATS; i++) {
-		xstats[count].name[0] = '\0';
 		xstats[count].id = count;
 		xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
 			rte_i40e_hw_port_strings[i].offset);
@@ -2303,7 +2301,6 @@ i40e_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 
 	for (i = 0; i < I40E_NB_RXQ_PRIO_XSTATS; i++) {
 		for (prio = 0; prio < 8; prio++) {
-			xstats[count].name[0] = '\0';
 			xstats[count].id = count;
 			xstats[count].value =
 				*(uint64_t *)(((char *)hw_stats) +
@@ -2315,7 +2312,6 @@ i40e_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 
 	for (i = 0; i < I40E_NB_TXQ_PRIO_XSTATS; i++) {
 		for (prio = 0; prio < 8; prio++) {
-			xstats[count].name[0] = '\0';
 			xstats[count].id = count;
 			xstats[count].value =
 				*(uint64_t *)(((char *)hw_stats) +
diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
index 4c5e45e..37af399 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -111,7 +111,7 @@ static int i40evf_dev_link_update(struct rte_eth_dev *dev,
 static void i40evf_dev_stats_get(struct rte_eth_dev *dev,
 				struct rte_eth_stats *stats);
 static int i40evf_dev_xstats_get(struct rte_eth_dev *dev,
-				 struct rte_eth_xstats *xstats, unsigned n);
+				 struct rte_eth_xstat *xstats, unsigned n);
 static int i40evf_dev_xstats_get_names(struct rte_eth_dev *dev,
 				       struct rte_eth_xstat_name *xstats_names,
 				       unsigned limit);
@@ -1005,7 +1005,7 @@ static int i40evf_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 }
 
 static int i40evf_dev_xstats_get(struct rte_eth_dev *dev,
-				 struct rte_eth_xstats *xstats, unsigned n)
+				 struct rte_eth_xstat *xstats, unsigned n)
 {
 	int ret;
 	unsigned i;
@@ -1023,7 +1023,6 @@ static int i40evf_dev_xstats_get(struct rte_eth_dev *dev,
 
 	/* loop over xstats array and values from pstats */
 	for (i = 0; i < I40EVF_NB_XSTATS; i++) {
-		xstats[i].name[0] = '\0';
 		xstats[i].id = i;
 		xstats[i].value = *(uint64_t *)(((char *)pstats) +
 			rte_i40evf_stats_strings[i].offset);
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 9e73492..125c257 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -174,9 +174,9 @@ static int ixgbe_dev_link_update(struct rte_eth_dev *dev,
 static void ixgbe_dev_stats_get(struct rte_eth_dev *dev,
 				struct rte_eth_stats *stats);
 static int ixgbe_dev_xstats_get(struct rte_eth_dev *dev,
-				struct rte_eth_xstats *xstats, unsigned n);
+				struct rte_eth_xstat *xstats, unsigned n);
 static int ixgbevf_dev_xstats_get(struct rte_eth_dev *dev,
-				  struct rte_eth_xstats *xstats, unsigned n);
+				  struct rte_eth_xstat *xstats, unsigned n);
 static void ixgbe_dev_stats_reset(struct rte_eth_dev *dev);
 static void ixgbe_dev_xstats_reset(struct rte_eth_dev *dev);
 static int ixgbe_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
@@ -2775,7 +2775,7 @@ static int ixgbevf_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 }
 
 static int
-ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
+ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
 					 unsigned n)
 {
 	struct ixgbe_hw *hw =
@@ -2808,7 +2808,6 @@ ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 	count = 0;
 	for (i = 0; i < IXGBE_NB_HW_STATS; i++) {
 		xstats[count].id = count;
-		xstats[count].name[0] = '\0';
 		xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
 				rte_ixgbe_stats_strings[i].offset);
 		count++;
@@ -2818,7 +2817,6 @@ ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 	for (stat = 0; stat < IXGBE_NB_RXQ_PRIO_STATS; stat++) {
 		for (i = 0; i < IXGBE_NB_RXQ_PRIO_VALUES; i++) {
 			xstats[count].id = count;
-			xstats[count].name[0] = '\0';
 			xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
 					rte_ixgbe_rxq_strings[stat].offset +
 					(sizeof(uint64_t) * i));
@@ -2830,7 +2828,6 @@ ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 	for (stat = 0; stat < IXGBE_NB_TXQ_PRIO_STATS; stat++) {
 		for (i = 0; i < IXGBE_NB_TXQ_PRIO_VALUES; i++) {
 			xstats[count].id = count;
-			xstats[count].name[0] = '\0';
 			xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
 					rte_ixgbe_txq_strings[stat].offset +
 					(sizeof(uint64_t) * i));
@@ -2884,7 +2881,7 @@ ixgbevf_update_stats(struct rte_eth_dev *dev)
 }
 
 static int
-ixgbevf_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
+ixgbevf_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
 		       unsigned n)
 {
 	struct ixgbevf_hw_stats *hw_stats = (struct ixgbevf_hw_stats *)
diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c
index 83df025..a833740 100644
--- a/drivers/net/virtio/virtio_ethdev.c
+++ b/drivers/net/virtio/virtio_ethdev.c
@@ -79,7 +79,7 @@ static void virtio_get_hwaddr(struct virtio_hw *hw);
 static void virtio_dev_stats_get(struct rte_eth_dev *dev,
 				 struct rte_eth_stats *stats);
 static int virtio_dev_xstats_get(struct rte_eth_dev *dev,
-				 struct rte_eth_xstats *xstats, unsigned n);
+				 struct rte_eth_xstat *xstats, unsigned n);
 static int virtio_dev_xstats_get_names(struct rte_eth_dev *dev,
 				       struct rte_eth_xstat_name *xstats_names,
 				       unsigned limit);
@@ -759,7 +759,7 @@ static int virtio_dev_xstats_get_names(struct rte_eth_dev *dev,
 }
 
 static int
-virtio_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
+virtio_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
 		      unsigned n)
 {
 	unsigned i;
@@ -780,7 +780,6 @@ virtio_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 		unsigned t;
 
 		for (t = 0; t < VIRTIO_NB_Q_XSTATS; t++) {
-			xstats[count].name[0] = '\0';
 			xstats[count].id = count;
 			xstats[count].value = *(uint64_t *)(((char *)rxvq) +
 				rte_virtio_q_stat_strings[t].offset);
@@ -797,7 +796,6 @@ virtio_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
 		unsigned t;
 
 		for (t = 0; t < VIRTIO_NB_Q_XSTATS; t++) {
-			xstats[count].name[0] = '\0';
 			xstats[count].id = count;
 			xstats[count].value = *(uint64_t *)(((char *)txvq) +
 				rte_virtio_q_stat_strings[t].offset);
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index 98e5efb..63320cc 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -1583,7 +1583,7 @@ rte_eth_xstats_get_names(uint8_t port_id,
 
 /* retrieve ethdev extended statistics */
 int
-rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
+rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstat *xstats,
 	unsigned n)
 {
 	struct rte_eth_stats eth_stats;
@@ -1625,7 +1625,6 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
 		stats_ptr = RTE_PTR_ADD(&eth_stats,
 					rte_stats_strings[i].offset);
 		val = *stats_ptr;
-		xstats[count].name[0] = '\0';
 		xstats[count].id = count + xcount;
 		xstats[count++].value = val;
 	}
@@ -1637,7 +1636,6 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
 					rte_rxq_stats_strings[i].offset +
 					q * sizeof(uint64_t));
 			val = *stats_ptr;
-			xstats[count].name[0] = '\0';
 			xstats[count].id = count + xcount;
 			xstats[count++].value = val;
 		}
@@ -1650,7 +1648,6 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
 					rte_txq_stats_strings[i].offset +
 					q * sizeof(uint64_t));
 			val = *stats_ptr;
-			xstats[count].name[0] = '\0';
 			xstats[count].id = count + xcount;
 			xstats[count++].value = val;
 		}
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index 5de86b8..440641e 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -914,8 +914,7 @@ struct rte_eth_txq_info {
  * statistics that are not provided in the generic rte_eth_stats
  * structure.
  */
-struct rte_eth_xstats {
-	char name[RTE_ETH_XSTATS_NAME_SIZE];
+struct rte_eth_xstat {
 	uint64_t id;
 	uint64_t value;
 };
@@ -1060,7 +1059,7 @@ typedef void (*eth_stats_reset_t)(struct rte_eth_dev *dev);
 /**< @internal Reset global I/O statistics of an Ethernet device to 0. */
 
 typedef int (*eth_xstats_get_t)(struct rte_eth_dev *dev,
-	struct rte_eth_xstats *stats, unsigned n);
+	struct rte_eth_xstat *stats, unsigned n);
 /**< @internal Get extended stats of an Ethernet device. */
 
 typedef void (*eth_xstats_reset_t)(struct rte_eth_dev *dev);
@@ -2314,7 +2313,7 @@ int rte_eth_xstats_get_names(uint8_t port_id,
  *     shall not be used by the caller.
  *   - negative value on error (invalid port id)
  */
-int rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
+int rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstat *xstats,
 		unsigned n);
 
 /**
-- 
2.5.5

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

* Re: [PATCH v5 0/7] Remove string operations from xstats
  2016-06-15 15:25       ` [PATCH v5 0/7] Remove string operations from xstats Remy Horton
                           ` (6 preceding siblings ...)
  2016-06-15 15:25         ` [PATCH v5 7/7] rte: change xstats usage to new API Remy Horton
@ 2016-06-16 16:02         ` Thomas Monjalon
  7 siblings, 0 replies; 71+ messages in thread
From: Thomas Monjalon @ 2016-06-16 16:02 UTC (permalink / raw)
  To: Remy Horton; +Cc: dev, John McNamara

> Remy Horton (7):
>   rte: change xstats to use integer ids
>   drivers/net/ixgbe: change xstats to use integer ids
>   drivers/net/e1000: change xstats to use integer ids
>   drivers/net/fm10k: change xstats to use integer ids
>   drivers/net/i40e: change xstats to use integer ids
>   drivers/net/virtio: change xstats to use integer ids
>   rte: change xstats usage to new API

Applied, thanks

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

* Re: [PATCH v5 6/7] drivers/net/virtio: change xstats to use integer ids
  2016-06-15 15:25         ` [PATCH v5 6/7] drivers/net/virtio: " Remy Horton
@ 2016-06-20 10:43           ` Yuanhan Liu
  0 siblings, 0 replies; 71+ messages in thread
From: Yuanhan Liu @ 2016-06-20 10:43 UTC (permalink / raw)
  To: Remy Horton; +Cc: dev, Thomas Monjalon

On Wed, Jun 15, 2016 at 04:25:32PM +0100, Remy Horton wrote:
>  
> +static int virtio_dev_xstats_get_names(struct rte_eth_dev *dev,
> +				       struct rte_eth_xstat_name *xstats_names,
> +				       __rte_unused unsigned limit)
> +{
> +	unsigned i;
> +	unsigned count = 0;
> +	unsigned t;
> +
> +	unsigned nstats = dev->data->nb_tx_queues * VIRTIO_NB_Q_XSTATS +
> +		dev->data->nb_rx_queues * VIRTIO_NB_Q_XSTATS;
> +
> +	if (xstats_names == NULL) {
> +		/* Note: limit checked in rte_eth_xstats_names() */
> +

That crashes testpmd while I run "show port xstats 0" with virtio PMD.
Will send a fix soon.

BTW, would you CC to the maintainer for corresponding subsystems next
time, say CC me for virtio/vhost changes?

	--yliu

> +		for (i = 0; i < dev->data->nb_rx_queues; i++) {
> +			struct virtqueue *rxvq = dev->data->rx_queues[i];
> +			if (rxvq == NULL)
> +				continue;
> +			for (t = 0; t < VIRTIO_NB_Q_XSTATS; t++) {
> +				snprintf(xstats_names[count].name,
> +					sizeof(xstats_names[count].name),
> +					"rx_q%u_%s", i,
> +					rte_virtio_q_stat_strings[t].name);
> +				xstats_names[count].id = count;
> +				count++;
> +			}
> +		}
> +
> +		for (i = 0; i < dev->data->nb_tx_queues; i++) {
> +			struct virtqueue *txvq = dev->data->tx_queues[i];
> +			if (txvq == NULL)
> +				continue;
> +			for (t = 0; t < VIRTIO_NB_Q_XSTATS; t++) {
> +				snprintf(xstats_names[count].name,
> +					sizeof(xstats_names[count].name),
> +					"tx_q%u_%s", i,
> +					rte_virtio_q_stat_strings[t].name);
> +				xstats_names[count].id = count;
> +				count++;
> +			}
> +		}
> +		return count;
> +	}
> +	return nstats;
> +}

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

end of thread, other threads:[~2016-06-20 10:43 UTC | newest]

Thread overview: 71+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-04-15 14:44 [RFC PATCH v1 0/3] Remove string operations from xstats Remy Horton
2016-04-15 14:44 ` [RFC PATCH v1 1/3] rte: change xstats to use integer keys Remy Horton
2016-04-29 13:17   ` David Harton (dharton)
2016-04-15 14:44 ` [RFC PATCH v1 2/3] drivers/net/ixgbe: change xstats to use integers Remy Horton
2016-04-29 13:43   ` David Harton (dharton)
2016-05-03 12:22     ` Remy Horton
2016-05-03 13:40       ` David Harton (dharton)
2016-04-15 14:44 ` [RFC PATCH v1 3/3] examples/ethtool: add xstats display command Remy Horton
2016-04-20 16:03 ` [RFC PATCH v1 0/3] Remove string operations from xstats David Harton (dharton)
2016-04-20 16:49   ` Mcnamara, John
2016-04-22 15:04     ` David Harton (dharton)
2016-04-28 14:56   ` Tahhan, Maryam
2016-04-28 15:58     ` David Harton (dharton)
2016-04-29 10:21       ` Remy Horton
2016-04-29 12:15         ` David Harton (dharton)
2016-04-29 12:52 ` David Harton (dharton)
2016-05-06 11:11 ` [RFC PATCH v2 " Remy Horton
2016-05-06 11:11   ` [RFC PATCH v2 1/3] rte: change xstats to use integer keys Remy Horton
2016-05-09 13:59     ` David Harton (dharton)
2016-05-10  8:58       ` Remy Horton
2016-05-12 16:17       ` Thomas Monjalon
2016-05-16 10:47     ` Tahhan, Maryam
2016-05-18  8:31     ` Tahhan, Maryam
2016-05-18  8:45       ` Remy Horton
2016-05-06 11:11   ` [RFC PATCH v2 2/3] drivers/net/ixgbe: change xstats to use integer id Remy Horton
2016-05-09 14:06     ` David Harton (dharton)
2016-05-18  8:41     ` Tahhan, Maryam
2016-05-06 11:11   ` [RFC PATCH v2 3/3] examples/ethtool: add xstats display command Remy Horton
2016-05-09 14:08     ` David Harton (dharton)
2016-05-18  8:42     ` Tahhan, Maryam
2016-05-16 10:42   ` [RFC PATCH v2 0/3] Remove string operations from xstats Tahhan, Maryam
2016-05-18 10:12     ` Remy Horton
2016-05-30 10:48   ` [PATCH v3 00/10] " Remy Horton
2016-05-30 10:48     ` [PATCH v3 01/10] rte: change xstats to use integer ids Remy Horton
2016-06-08  9:37       ` Thomas Monjalon
2016-06-08 11:16         ` Remy Horton
2016-06-08 12:22           ` Thomas Monjalon
2016-05-30 10:48     ` [PATCH v3 02/10] drivers/net/ixgbe: " Remy Horton
2016-05-30 10:48     ` [PATCH v3 03/10] drivers/net/e1000: " Remy Horton
2016-05-30 10:48     ` [PATCH v3 04/10] drivers/net/fm10k: " Remy Horton
2016-05-30 10:48     ` [PATCH v3 05/10] drivers/net/i40e: " Remy Horton
2016-05-30 10:48     ` [PATCH v3 06/10] drivers/net/virtio: " Remy Horton
2016-05-30 10:48     ` [PATCH v3 07/10] app/test-pmd: " Remy Horton
2016-05-30 10:48     ` [PATCH v3 08/10] app/proc_info: " Remy Horton
2016-05-30 10:48     ` [PATCH v3 09/10] remove name field from struct rte_eth_xstats Remy Horton
2016-06-08 12:23       ` Thomas Monjalon
2016-05-30 10:48     ` [PATCH v3 10/10] doc: update xstats documentation Remy Horton
2016-06-09  8:48       ` Mcnamara, John
2016-06-06 12:45     ` [PATCH v3 00/10] Remove string operations from xstats David Harton (dharton)
2016-06-13 15:51     ` [PATCH v4 0/8] " Remy Horton
2016-06-13 15:51       ` [PATCH v4 1/8] rte: change xstats to use integer ids Remy Horton
2016-06-15  9:19         ` Thomas Monjalon
2016-06-13 15:51       ` [PATCH v4 2/8] drivers/net/ixgbe: " Remy Horton
2016-06-13 15:51       ` [PATCH v4 3/8] drivers/net/e1000: " Remy Horton
2016-06-13 15:51       ` [PATCH v4 4/8] drivers/net/fm10k: " Remy Horton
2016-06-13 15:51       ` [PATCH v4 5/8] drivers/net/i40e: " Remy Horton
2016-06-13 15:51       ` [PATCH v4 6/8] drivers/net/virtio: " Remy Horton
2016-06-13 15:52       ` [PATCH v4 7/8] rte: change xstats usage to new API Remy Horton
2016-06-15  9:13         ` Thomas Monjalon
2016-06-13 15:52       ` [PATCH v4 8/8] doc: update xstats documentation Remy Horton
2016-06-14 14:06         ` Mcnamara, John
2016-06-15 15:25       ` [PATCH v5 0/7] Remove string operations from xstats Remy Horton
2016-06-15 15:25         ` [PATCH v5 1/7] rte: change xstats to use integer ids Remy Horton
2016-06-15 15:25         ` [PATCH v5 2/7] drivers/net/ixgbe: " Remy Horton
2016-06-15 15:25         ` [PATCH v5 3/7] drivers/net/e1000: " Remy Horton
2016-06-15 15:25         ` [PATCH v5 4/7] drivers/net/fm10k: " Remy Horton
2016-06-15 15:25         ` [PATCH v5 5/7] drivers/net/i40e: " Remy Horton
2016-06-15 15:25         ` [PATCH v5 6/7] drivers/net/virtio: " Remy Horton
2016-06-20 10:43           ` Yuanhan Liu
2016-06-15 15:25         ` [PATCH v5 7/7] rte: change xstats usage to new API Remy Horton
2016-06-16 16:02         ` [PATCH v5 0/7] Remove string operations from xstats Thomas Monjalon

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.