All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] extend API to retriving xstats by group and xstats by name
@ 2017-03-02 16:07 Kuba Kozak
  2017-03-02 16:07 ` [PATCH 1/4] ethdev: add retrieving " Kuba Kozak
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Kuba Kozak @ 2017-03-02 16:07 UTC (permalink / raw)
  To: dev; +Cc: Kuba Kozak

Added three new functions to API: rte_eth_xstats_get_by_name(),
rte_eth_xstats_get_by_group(), rte_eth_xstats_get_names_by_group().

Extension of the 'rte_igb_xstats_name_off' structure
with additional field 'group_mask'. For each xstats there is now
specified group (e.g. TX_GROUP), one xstatistic can be in several groups.
To implement new functionality of retriving xstats by group
on e1000 driver level, there are two functions added:
eth_igb_xstats_get_by_group() and eth_igb_xstats_get_names_by_group(),
on ixgbe driver level, there are new functions added:
ixgbe_dev_xstats_get_by_group() and ixgbe_dev_xstats_get_names_by_group()

Extended functionality of proc_info application:
--xstats-name NAME: to display single xstat value by NAME
--xstats-group GROUPNAME: to display group of xstats by GROUPNAME

Jacek Piasecki (4):
  ethdev: add retrieving xstats by group and xstats by name
  net/e1000: add grouping of xstats for e1000 driver
  net/ixgbe: add grouping of xstats for ixgbe driver
  app/proc_info: add support for xstats-name and xstats-group

 app/proc_info/main.c             | 112 +++++++-
 drivers/net/e1000/igb_ethdev.c   | 268 +++++++++++++-----
 drivers/net/ixgbe/ixgbe_ethdev.c | 586 +++++++++++++++++++++++++++++++--------
 lib/librte_ether/rte_ethdev.c    | 310 ++++++++++++++++++++-
 lib/librte_ether/rte_ethdev.h    | 105 ++++++-
 5 files changed, 1193 insertions(+), 188 deletions(-)

-- 
1.9.1

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

* [PATCH 1/4] ethdev: add retrieving xstats by group and xstats by name
  2017-03-02 16:07 [PATCH 0/4] extend API to retriving xstats by group and xstats by name Kuba Kozak
@ 2017-03-02 16:07 ` Kuba Kozak
  2017-03-02 16:07 ` [PATCH 2/4] net/e1000: add grouping of xstats for e1000 driver Kuba Kozak
  2017-03-02 16:07 ` [PATCH 3/4] net/ixgbe: add grouping of xstats for ixgbe driver Kuba Kozak
  2 siblings, 0 replies; 6+ messages in thread
From: Kuba Kozak @ 2017-03-02 16:07 UTC (permalink / raw)
  To: dev; +Cc: Jacek Piasecki, Kuba Kozak

From: Jacek Piasecki <jacekx.piasecki@intel.com>

This patch extends library for retriving xstats by specified groups and
single xstat by given name.

Signed-off-by: Jacek Piasecki <jacekx.piasecki@intel.com>
Signed-off-by: Kuba Kozak <kubax.kozak@intel.com>
---
 lib/librte_ether/rte_ethdev.c | 310 ++++++++++++++++++++++++++++++++++++++++--
 lib/librte_ether/rte_ethdev.h | 105 +++++++++++++-
 2 files changed, 401 insertions(+), 14 deletions(-)

diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index eb0a94a..e18ca1d 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -87,33 +87,37 @@
 struct rte_eth_xstats_name_off {
 	char name[RTE_ETH_XSTATS_NAME_SIZE];
 	unsigned offset;
+	uint64_t group_mask;
 };
 
 static const struct rte_eth_xstats_name_off rte_stats_strings[] = {
-	{"rx_good_packets", offsetof(struct rte_eth_stats, ipackets)},
-	{"tx_good_packets", offsetof(struct rte_eth_stats, opackets)},
-	{"rx_good_bytes", offsetof(struct rte_eth_stats, ibytes)},
-	{"tx_good_bytes", offsetof(struct rte_eth_stats, obytes)},
-	{"rx_errors", offsetof(struct rte_eth_stats, ierrors)},
-	{"tx_errors", offsetof(struct rte_eth_stats, oerrors)},
+	{"rx_good_packets", offsetof(struct rte_eth_stats, ipackets), RX_GROUP},
+	{"tx_good_packets", offsetof(struct rte_eth_stats, opackets), TX_GROUP},
+	{"rx_good_bytes", offsetof(struct rte_eth_stats, ibytes), RX_GROUP},
+	{"tx_good_bytes", offsetof(struct rte_eth_stats, obytes), TX_GROUP},
+	{"rx_errors", offsetof(struct rte_eth_stats, ierrors),
+			RX_GROUP | ERR_GROUP},
+	{"tx_errors", offsetof(struct rte_eth_stats, oerrors),
+			TX_GROUP | ERR_GROUP},
 	{"rx_mbuf_allocation_errors", offsetof(struct rte_eth_stats,
-		rx_nombuf)},
+		rx_nombuf), RX_GROUP | ERR_GROUP},
 };
 
 #define RTE_NB_STATS (sizeof(rte_stats_strings) / sizeof(rte_stats_strings[0]))
 
 static const struct rte_eth_xstats_name_off rte_rxq_stats_strings[] = {
-	{"packets", offsetof(struct rte_eth_stats, q_ipackets)},
-	{"bytes", offsetof(struct rte_eth_stats, q_ibytes)},
-	{"errors", offsetof(struct rte_eth_stats, q_errors)},
+	{"packets", offsetof(struct rte_eth_stats, q_ipackets), RXQ_GROUP},
+	{"bytes", offsetof(struct rte_eth_stats, q_ibytes), RXQ_GROUP},
+	{"errors", offsetof(struct rte_eth_stats, q_errors),
+			RXQ_GROUP | ERR_GROUP},
 };
 
 #define RTE_NB_RXQ_STATS (sizeof(rte_rxq_stats_strings) /	\
 		sizeof(rte_rxq_stats_strings[0]))
 
 static const struct rte_eth_xstats_name_off rte_txq_stats_strings[] = {
-	{"packets", offsetof(struct rte_eth_stats, q_opackets)},
-	{"bytes", offsetof(struct rte_eth_stats, q_obytes)},
+	{"packets", offsetof(struct rte_eth_stats, q_opackets), TXQ_GROUP},
+	{"bytes", offsetof(struct rte_eth_stats, q_obytes), TXQ_GROUP},
 };
 #define RTE_NB_TXQ_STATS (sizeof(rte_txq_stats_strings) /	\
 		sizeof(rte_txq_stats_strings[0]))
@@ -1448,6 +1452,110 @@ struct rte_eth_dev *
 	return count;
 }
 
+static int
+get_xstats_count_by_group(uint8_t port_id, uint64_t group_mask)
+{
+	struct rte_eth_dev *dev;
+	int count = 0;
+	int dcount = 0;
+	unsigned i;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL);
+	dev = &rte_eth_devices[port_id];
+	if (dev->dev_ops->xstats_get_names_by_group != NULL) {
+		dcount = (*dev->dev_ops->xstats_get_names_by_group)
+				(dev, NULL, 0, group_mask);
+		if (dcount < 0)
+			return dcount;
+	}
+
+
+
+
+	for (i = 0; i < RTE_NB_STATS; i++) {
+		if (rte_stats_strings[i].group_mask & group_mask)
+			count++;
+	}
+	for (i = 0; i < RTE_NB_RXQ_STATS; i++) {
+		if (rte_rxq_stats_strings[i].group_mask & group_mask)
+			count += RTE_MIN(dev->data->nb_rx_queues,
+					RTE_ETHDEV_QUEUE_STAT_CNTRS);
+	}
+	for (i = 0; i < RTE_NB_TXQ_STATS; i++) {
+		if (rte_txq_stats_strings[i].group_mask & group_mask)
+			count += RTE_MIN(dev->data->nb_tx_queues,
+					RTE_ETHDEV_QUEUE_STAT_CNTRS);
+	}
+	return count+dcount;
+}
+
+int
+rte_eth_xstats_get_by_name(uint8_t port_id, struct rte_eth_xstat *xstat,
+		const char *name)
+{
+	struct rte_eth_xstat *xstats;
+	int cnt_xstats, idx_xstat;
+	struct rte_eth_xstat_name *xstats_names;
+
+
+
+	/* 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 -1;
+	}
+
+	/* 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 -1;
+	}
+	if (cnt_xstats != rte_eth_xstats_get_names(
+			port_id, xstats_names, cnt_xstats)) {
+		printf("Error: Cannot get xstats lookup\n");
+		free(xstats_names);
+		return -1;
+	}
+
+	/* 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 -1;
+	}
+
+	if (cnt_xstats != rte_eth_xstats_get(port_id, xstats, cnt_xstats)) {
+		printf("Error: Unable to get xstats\n");
+		free(xstats_names);
+		free(xstats);
+		return -1;
+	}
+
+	if (!xstat) {
+		printf("Error: xstat pointer is NULL\n");
+		free(xstats_names);
+		free(xstats);
+		return -1;
+	}
+
+	/* Display xstats */
+	for (idx_xstat = 0; idx_xstat < cnt_xstats; idx_xstat++) {
+		if (!strcmp(xstats_names[idx_xstat].name, name)) {
+
+			xstat->id = xstats[idx_xstat].id;
+			xstat->value = xstats[idx_xstat].value;
+			return 0;
+		};
+	}
+
+	free(xstats_names);
+	free(xstats);
+	return -1;
+}
+
 int
 rte_eth_xstats_get_names(uint8_t port_id,
 	struct rte_eth_xstat_name *xstats_names,
@@ -1513,6 +1621,83 @@ struct rte_eth_dev *
 	return cnt_used_entries;
 }
 
+int
+rte_eth_xstats_get_names_by_group(uint8_t port_id,
+	struct rte_eth_xstat_name *xstats_names,
+	unsigned size, __rte_unused uint64_t group_mask)
+{
+	struct rte_eth_dev *dev;
+	int cnt_used_entries;
+	int cnt_expected_entries;
+	int cnt_driver_entries;
+	uint32_t idx, id_queue;
+	uint16_t num_q;
+
+	cnt_expected_entries = get_xstats_count_by_group(port_id, group_mask);
+	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];
+	cnt_used_entries = 0;
+
+	for (idx = 0; idx < RTE_NB_STATS; idx++) {
+		if (rte_stats_strings[idx].group_mask & group_mask) {
+			snprintf(xstats_names[cnt_used_entries].name,
+				sizeof(xstats_names[0].name),
+				"%s", rte_stats_strings[idx].name);
+			cnt_used_entries++;
+		}
+	}
+	num_q = RTE_MIN(dev->data->nb_rx_queues, RTE_ETHDEV_QUEUE_STAT_CNTRS);
+	for (id_queue = 0; id_queue < num_q; id_queue++) {
+		for (idx = 0; idx < RTE_NB_RXQ_STATS; idx++) {
+			if (rte_rxq_stats_strings[idx].group_mask &
+					group_mask) {
+				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++;
+			}
+		}
+	}
+	num_q = RTE_MIN(dev->data->nb_tx_queues, RTE_ETHDEV_QUEUE_STAT_CNTRS);
+	for (id_queue = 0; id_queue < num_q; id_queue++) {
+		for (idx = 0; idx < RTE_NB_TXQ_STATS; idx++) {
+			if (rte_txq_stats_strings[idx].group_mask &
+					group_mask) {
+				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++;
+			}
+
+		}
+	}
+
+	if (dev->dev_ops->xstats_get_names != NULL) {
+		/* If there are any driver-specific xstats, append them
+		 * to end of list.
+		 */
+		cnt_driver_entries =
+				(*dev->dev_ops->xstats_get_names_by_group)(
+			dev,
+			xstats_names + cnt_used_entries,
+			size - cnt_used_entries,
+			group_mask);
+		if (cnt_driver_entries < 0)
+			return cnt_driver_entries;
+		cnt_used_entries += cnt_driver_entries;
+	}
+
+	return cnt_used_entries;
+}
+
 /* retrieve ethdev extended statistics */
 int
 rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstat *xstats,
@@ -1595,6 +1780,104 @@ struct rte_eth_dev *
 	return count + xcount;
 }
 
+/* retrieve ethdev extended statistics */
+int
+rte_eth_xstats_get_by_group(uint8_t port_id, struct rte_eth_xstat *xstats,
+	unsigned n, uint64_t group_mask)
+{
+	struct rte_eth_stats eth_stats;
+	struct rte_eth_dev *dev;
+	unsigned count = 0, i, q;
+	signed xcount = 0;
+	uint64_t val, *stats_ptr;
+	uint16_t nb_rxqs, nb_txqs;
+
+	RTE_ETH_VALID_PORTID_OR_ERR_RET(port_id, -EINVAL);
+
+	dev = &rte_eth_devices[port_id];
+
+	nb_rxqs = RTE_MIN(dev->data->nb_rx_queues, RTE_ETHDEV_QUEUE_STAT_CNTRS);
+	nb_txqs = RTE_MIN(dev->data->nb_tx_queues, RTE_ETHDEV_QUEUE_STAT_CNTRS);
+
+	for (i = 0; i < RTE_NB_STATS; i++) {
+		if (rte_stats_strings[i].group_mask & group_mask)
+			count++;
+	}
+	for (i = 0; i < RTE_NB_RXQ_STATS; i++) {
+		if (rte_rxq_stats_strings[i].group_mask & group_mask)
+			count += nb_rxqs;
+	}
+	for (i = 0; i < RTE_NB_TXQ_STATS; i++) {
+		if (rte_txq_stats_strings[i].group_mask & group_mask)
+			count += nb_txqs;
+	}
+
+	/* implemented by the driver */
+	if (dev->dev_ops->xstats_get_by_group != NULL) {
+		/* Retrieve the xstats from the driver at the end of the
+		 * xstats struct.
+		 */
+		xcount = (*dev->dev_ops->xstats_get_by_group)(dev,
+				xstats ? xstats + count : NULL,
+				(n > count) ? n - count : 0,
+				group_mask);
+
+		if (xcount < 0)
+			return xcount;
+	}
+
+	if (n < count + xcount || xstats == NULL)
+		return count + xcount;
+
+	/* now fill the xstats structure */
+	count = 0;
+	rte_eth_stats_get(port_id, &eth_stats);
+
+	/* global stats */
+	for (i = 0; i < RTE_NB_STATS; i++) {
+		if (rte_stats_strings[i].group_mask & group_mask) {
+			stats_ptr = RTE_PTR_ADD(&eth_stats,
+						rte_stats_strings[i].offset);
+			val = *stats_ptr;
+			xstats[count++].value = val;
+		}
+	}
+
+	/* per-rxq stats */
+	for (q = 0; q < nb_rxqs; q++) {
+		for (i = 0; i < RTE_NB_RXQ_STATS; i++) {
+			if (rte_rxq_stats_strings[i].group_mask & group_mask) {
+				stats_ptr = RTE_PTR_ADD(&eth_stats,
+						rte_rxq_stats_strings[i].offset
+						+ q * sizeof(uint64_t));
+				val = *stats_ptr;
+				xstats[count++].value = val;
+			}
+		}
+	}
+
+	/* per-txq stats */
+	for (q = 0; q < nb_txqs; q++) {
+		for (i = 0; i < RTE_NB_TXQ_STATS; i++) {
+			if (rte_txq_stats_strings[i].group_mask & group_mask) {
+				stats_ptr = RTE_PTR_ADD(&eth_stats,
+						rte_txq_stats_strings[i].offset
+						+ q * sizeof(uint64_t));
+				val = *stats_ptr;
+				xstats[count++].value = val;
+			}
+		}
+	}
+
+	for (i = 0; i < count; i++)
+		xstats[i].id = i;
+	/* add an offset to driver-specific stats */
+	for ( ; i < count + xcount; i++)
+		xstats[i].id += count;
+
+	return count + xcount;
+}
+
 /* reset ethdev extended statistics */
 void
 rte_eth_xstats_reset(uint8_t port_id)
@@ -1624,7 +1907,8 @@ struct rte_eth_dev *
 
 	dev = &rte_eth_devices[port_id];
 
-	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->queue_stats_mapping_set, -ENOTSUP);
+	RTE_FUNC_PTR_OR_ERR_RET(*dev->dev_ops->queue_stats_mapping_set,
+			-ENOTSUP);
 	return (*dev->dev_ops->queue_stats_mapping_set)
 			(dev, queue_id, stat_idx, is_rx);
 }
diff --git a/lib/librte_ether/rte_ethdev.h b/lib/librte_ether/rte_ethdev.h
index c17bbda..d7cdca2 100644
--- a/lib/librte_ether/rte_ethdev.h
+++ b/lib/librte_ether/rte_ethdev.h
@@ -990,6 +990,17 @@ struct rte_eth_xstat_name {
 #define ETH_MAX_VMDQ_POOL  64
 
 /**
+ * Xstats groups by bit no. in 'group_mask'
+ */
+#define TX_GROUP	0x0001
+#define RX_GROUP	0x0002
+#define ERR_GROUP	0x0004
+#define TXQ_GROUP	0x0008
+#define RXQ_GROUP	0x0010
+#define VF_GROUP	0x0020
+#define MAC_GROUP	0x0040
+
+/**
  * A structure used to get the information of queue and
  * TC mapping on both TX and RX paths.
  */
@@ -1118,6 +1129,10 @@ typedef int (*eth_xstats_get_t)(struct rte_eth_dev *dev,
 	struct rte_eth_xstat *stats, unsigned n);
 /**< @internal Get extended stats of an Ethernet device. */
 
+typedef int (*eth_xstats_get_by_group_t)(struct rte_eth_dev *dev,
+	struct rte_eth_xstat *stats, unsigned n, uint64_t group_mask);
+/**< @internal Get extended stats of an Ethernet device. */
+
 typedef void (*eth_xstats_reset_t)(struct rte_eth_dev *dev);
 /**< @internal Reset extended stats of an Ethernet device. */
 
@@ -1125,6 +1140,17 @@ 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_xstats_get_names_by_group_t)(struct rte_eth_dev *dev,
+	struct rte_eth_xstat_name *xstats_names,
+	unsigned size, uint64_t group_mask);
+/**< @internal Get names of extended stats of an Ethernet device. */
+
+typedef int (*eth_xstats_get_by_name_t)(struct rte_eth_dev *dev,
+		struct rte_eth_xstat_name *xstats_names,
+		struct rte_eth_xstat *xstat,
+		const char *name);
+/**< @internal Get xstat specified by name 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,
@@ -1456,8 +1482,13 @@ struct eth_dev_ops {
 	eth_stats_get_t            stats_get;     /**< Get generic device statistics. */
 	eth_stats_reset_t          stats_reset;   /**< Reset generic device statistics. */
 	eth_xstats_get_t           xstats_get;    /**< Get extended device statistics. */
+	eth_xstats_get_by_group_t  xstats_get_by_group;
+	/**< Get extended device statistics. */
 	eth_xstats_reset_t         xstats_reset;  /**< Reset extended device statistics. */
-	eth_xstats_get_names_t     xstats_get_names;
+	eth_xstats_get_names_t	   xstats_get_names;
+	eth_xstats_get_names_by_group_t xstats_get_names_by_group;
+	eth_xstats_get_by_name_t	xstats_get_by_name;
+
 	/**< Get names of extended statistics. */
 	eth_queue_stats_mapping_set_t queue_stats_mapping_set;
 	/**< Configure per queue stat counter mapping. */
@@ -2307,6 +2338,51 @@ int rte_eth_xstats_get_names(uint8_t port_id,
 		unsigned size);
 
 /**
+ * Get extended statistics of an Ethernet device matching specified name.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param name
+ *   Phrase used to search extended statistics
+ * @param name *xstat
+ *   Pointer to allocated memory for rte_eth_xstat structure
+ * @return
+ *   - 0 when xstat was successfully found and value and id were returned
+ *   using pointer to rte_eth_xstat,
+ *   - A negative value when xstat wasn't found.
+ */
+int
+rte_eth_xstats_get_by_name(uint8_t port_id, struct rte_eth_xstat *xstat,
+		const char *name);
+
+
+/**
+ * Retrieve names of extended grouped statistics of an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param xstats_names
+ *   An rte_eth_xstat_name array of at least *size* elements to
+ *   be filled. If set to NULL, the function returns the required number
+ *   of elements.
+ * @param size
+ *   The size of the xstats_names array (number of elements).
+ * @param group_id
+ *   Group identificator
+ * @return
+ *   - A positive value lower or equal to size: success. The return value
+ *     is the number of entries filled in the stats table.
+ *   - A positive value higher than size: error, the given statistics table
+ *     is too small. The return value corresponds to the size that should
+ *     be given to succeed. The entries in the table are not valid and
+ *     shall not be used by the caller.
+ */
+int
+rte_eth_xstats_get_names_by_group(uint8_t port_id,
+	struct rte_eth_xstat_name *xstats_names,
+	unsigned size, uint64_t group_mask);
+
+/**
  * Retrieve extended statistics of an Ethernet device.
  *
  * @param port_id
@@ -2332,6 +2408,33 @@ int rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstat *xstats,
 		unsigned n);
 
 /**
+ * Retrieve extended grouped statistics of an Ethernet device.
+ *
+ * @param port_id
+ *   The port identifier of the Ethernet device.
+ * @param xstats
+ *   A pointer to a table of structure of type *rte_eth_xstat*
+ *   to be filled with device statistics ids and values: id is the
+ *   index of the name string in xstats_names (see rte_eth_xstats_get_names()),
+ *   and value is the statistic counter.
+ *   This parameter can be set to NULL if n is 0.
+ * @param n
+ *   The size of the xstats array (number of elements).
+ * @param group_id
+ *   Group identificator
+ * @return
+ *   - A positive value lower or equal to n: success. The return value
+ *     is the number of entries filled in the stats table.
+ *   - A positive value higher than n: 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.
+ *   - A negative value on error (invalid port id).
+ */
+int rte_eth_xstats_get_by_group(uint8_t port_id, struct rte_eth_xstat *xstats,
+		unsigned n, uint64_t group_mask);
+
+/**
  * Reset extended statistics of an Ethernet device.
  *
  * @param port_id
-- 
1.9.1

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

* [PATCH 2/4] net/e1000: add grouping of xstats for e1000 driver
  2017-03-02 16:07 [PATCH 0/4] extend API to retriving xstats by group and xstats by name Kuba Kozak
  2017-03-02 16:07 ` [PATCH 1/4] ethdev: add retrieving " Kuba Kozak
@ 2017-03-02 16:07 ` Kuba Kozak
  2017-03-03  1:35   ` Lu, Wenzhuo
  2017-03-02 16:07 ` [PATCH 3/4] net/ixgbe: add grouping of xstats for ixgbe driver Kuba Kozak
  2 siblings, 1 reply; 6+ messages in thread
From: Kuba Kozak @ 2017-03-02 16:07 UTC (permalink / raw)
  To: dev; +Cc: Jacek Piasecki, Kuba Kozak

From: Jacek Piasecki <jacekx.piasecki@intel.com>

This patch extends the 'rte_igb_xstats_name_off' structure
with additional field 'group_mask'. For each xstats there is now
specified group (e.g. TX_GROUP), one xstatistic can be in several groups.
To implement new functionality of retriving xstats by group
on driver level, there are two functions added:
eth_igb_xstats_get_by_group() and eth_igb_xstats_get_names_by_group()

Signed-off-by: Jacek Piasecki <jacekx.piasecki@intel.com>
Signed-off-by: Kuba Kozak <kubax.kozak@intel.com>
---
 drivers/net/e1000/igb_ethdev.c | 268 +++++++++++++++++++++++++++++++----------
 1 file changed, 206 insertions(+), 62 deletions(-)

diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index a112b38..8057b6f 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -115,9 +115,18 @@ 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_xstat *xstats, unsigned n);
+static
+int eth_igb_xstats_get_by_group(struct rte_eth_dev *dev,
+		struct rte_eth_xstat *xstats,
+		unsigned n, uint64_t group_mask);
 static int eth_igb_xstats_get_names(struct rte_eth_dev *dev,
 				    struct rte_eth_xstat_name *xstats_names,
 				    unsigned limit);
+static int
+eth_igb_xstats_get_names_by_group(__rte_unused struct rte_eth_dev *dev,
+	struct rte_eth_xstat_name *xstats_names,
+	__rte_unused unsigned limit,
+	uint64_t group_mask);
 static void eth_igb_stats_reset(struct rte_eth_dev *dev);
 static void eth_igb_xstats_reset(struct rte_eth_dev *dev);
 static int eth_igb_fw_version_get(struct rte_eth_dev *dev,
@@ -390,7 +399,9 @@ static void eth_igbvf_interrupt_handler(struct rte_intr_handle *handle,
 	.link_update          = eth_igb_link_update,
 	.stats_get            = eth_igb_stats_get,
 	.xstats_get           = eth_igb_xstats_get,
+	.xstats_get_by_group  = eth_igb_xstats_get_by_group,
 	.xstats_get_names     = eth_igb_xstats_get_names,
+	.xstats_get_names_by_group = eth_igb_xstats_get_names_by_group,
 	.stats_reset          = eth_igb_stats_reset,
 	.xstats_reset         = eth_igb_xstats_reset,
 	.fw_version_get       = eth_igb_fw_version_get,
@@ -473,78 +484,128 @@ static void eth_igbvf_interrupt_handler(struct rte_intr_handle *handle,
 struct rte_igb_xstats_name_off {
 	char name[RTE_ETH_XSTATS_NAME_SIZE];
 	unsigned offset;
+	uint64_t group_mask;
 };
 
 static const struct rte_igb_xstats_name_off rte_igb_stats_strings[] = {
-	{"rx_crc_errors", offsetof(struct e1000_hw_stats, crcerrs)},
-	{"rx_align_errors", offsetof(struct e1000_hw_stats, algnerrc)},
-	{"rx_symbol_errors", offsetof(struct e1000_hw_stats, symerrs)},
-	{"rx_missed_packets", offsetof(struct e1000_hw_stats, mpc)},
-	{"tx_single_collision_packets", offsetof(struct e1000_hw_stats, scc)},
-	{"tx_multiple_collision_packets", offsetof(struct e1000_hw_stats, mcc)},
+	{"rx_crc_errors", offsetof(struct e1000_hw_stats, crcerrs),
+			RX_GROUP | ERR_GROUP},
+	{"rx_align_errors", offsetof(struct e1000_hw_stats, algnerrc),
+			RX_GROUP | ERR_GROUP},
+	{"rx_symbol_errors", offsetof(struct e1000_hw_stats, symerrs),
+			RX_GROUP | ERR_GROUP},
+	{"rx_missed_packets", offsetof(struct e1000_hw_stats, mpc),
+			RX_GROUP},
+	{"tx_single_collision_packets", offsetof(struct e1000_hw_stats, scc),
+			TX_GROUP},
+	{"tx_multiple_collision_packets", offsetof(struct e1000_hw_stats, mcc),
+			TX_GROUP},
 	{"tx_excessive_collision_packets", offsetof(struct e1000_hw_stats,
-		ecol)},
-	{"tx_late_collisions", offsetof(struct e1000_hw_stats, latecol)},
-	{"tx_total_collisions", offsetof(struct e1000_hw_stats, colc)},
-	{"tx_deferred_packets", offsetof(struct e1000_hw_stats, dc)},
-	{"tx_no_carrier_sense_packets", offsetof(struct e1000_hw_stats, tncrs)},
-	{"rx_carrier_ext_errors", offsetof(struct e1000_hw_stats, cexterr)},
-	{"rx_length_errors", offsetof(struct e1000_hw_stats, rlec)},
-	{"rx_xon_packets", offsetof(struct e1000_hw_stats, xonrxc)},
-	{"tx_xon_packets", offsetof(struct e1000_hw_stats, xontxc)},
-	{"rx_xoff_packets", offsetof(struct e1000_hw_stats, xoffrxc)},
-	{"tx_xoff_packets", offsetof(struct e1000_hw_stats, xofftxc)},
+		ecol), TX_GROUP},
+	{"tx_late_collisions", offsetof(struct e1000_hw_stats, latecol),
+			TX_GROUP},
+	{"tx_total_collisions", offsetof(struct e1000_hw_stats, colc),
+			TX_GROUP},
+	{"tx_deferred_packets", offsetof(struct e1000_hw_stats, dc),
+			TX_GROUP},
+	{"tx_no_carrier_sense_packets", offsetof(struct e1000_hw_stats, tncrs),
+			TX_GROUP},
+	{"rx_carrier_ext_errors", offsetof(struct e1000_hw_stats, cexterr),
+			RX_GROUP | ERR_GROUP},
+	{"rx_length_errors", offsetof(struct e1000_hw_stats, rlec),
+			RX_GROUP | ERR_GROUP},
+	{"rx_xon_packets", offsetof(struct e1000_hw_stats, xonrxc),
+			RX_GROUP},
+	{"tx_xon_packets", offsetof(struct e1000_hw_stats, xontxc),
+			TX_GROUP},
+	{"rx_xoff_packets", offsetof(struct e1000_hw_stats, xoffrxc),
+			RX_GROUP},
+	{"tx_xoff_packets", offsetof(struct e1000_hw_stats, xofftxc),
+			TX_GROUP},
 	{"rx_flow_control_unsupported_packets", offsetof(struct e1000_hw_stats,
-		fcruc)},
-	{"rx_size_64_packets", offsetof(struct e1000_hw_stats, prc64)},
-	{"rx_size_65_to_127_packets", offsetof(struct e1000_hw_stats, prc127)},
-	{"rx_size_128_to_255_packets", offsetof(struct e1000_hw_stats, prc255)},
-	{"rx_size_256_to_511_packets", offsetof(struct e1000_hw_stats, prc511)},
+		fcruc), RX_GROUP},
+	{"rx_size_64_packets", offsetof(struct e1000_hw_stats, prc64),
+			RX_GROUP},
+	{"rx_size_65_to_127_packets", offsetof(struct e1000_hw_stats, prc127),
+			RX_GROUP},
+	{"rx_size_128_to_255_packets", offsetof(struct e1000_hw_stats, prc255),
+			RX_GROUP},
+	{"rx_size_256_to_511_packets", offsetof(struct e1000_hw_stats, prc511),
+			RX_GROUP},
 	{"rx_size_512_to_1023_packets", offsetof(struct e1000_hw_stats,
-		prc1023)},
+		prc1023), RX_GROUP},
 	{"rx_size_1024_to_max_packets", offsetof(struct e1000_hw_stats,
-		prc1522)},
-	{"rx_broadcast_packets", offsetof(struct e1000_hw_stats, bprc)},
-	{"rx_multicast_packets", offsetof(struct e1000_hw_stats, mprc)},
-	{"rx_undersize_errors", offsetof(struct e1000_hw_stats, ruc)},
-	{"rx_fragment_errors", offsetof(struct e1000_hw_stats, rfc)},
-	{"rx_oversize_errors", offsetof(struct e1000_hw_stats, roc)},
-	{"rx_jabber_errors", offsetof(struct e1000_hw_stats, rjc)},
-	{"rx_management_packets", offsetof(struct e1000_hw_stats, mgprc)},
-	{"rx_management_dropped", offsetof(struct e1000_hw_stats, mgpdc)},
-	{"tx_management_packets", offsetof(struct e1000_hw_stats, mgptc)},
-	{"rx_total_packets", offsetof(struct e1000_hw_stats, tpr)},
-	{"tx_total_packets", offsetof(struct e1000_hw_stats, tpt)},
-	{"rx_total_bytes", offsetof(struct e1000_hw_stats, tor)},
-	{"tx_total_bytes", offsetof(struct e1000_hw_stats, tot)},
-	{"tx_size_64_packets", offsetof(struct e1000_hw_stats, ptc64)},
-	{"tx_size_65_to_127_packets", offsetof(struct e1000_hw_stats, ptc127)},
-	{"tx_size_128_to_255_packets", offsetof(struct e1000_hw_stats, ptc255)},
-	{"tx_size_256_to_511_packets", offsetof(struct e1000_hw_stats, ptc511)},
+		prc1522), RX_GROUP},
+	{"rx_broadcast_packets", offsetof(struct e1000_hw_stats, bprc),
+			RX_GROUP},
+	{"rx_multicast_packets", offsetof(struct e1000_hw_stats, mprc),
+			RX_GROUP},
+	{"rx_undersize_errors", offsetof(struct e1000_hw_stats, ruc),
+			RX_GROUP | ERR_GROUP},
+	{"rx_fragment_errors", offsetof(struct e1000_hw_stats, rfc),
+			RX_GROUP | ERR_GROUP},
+	{"rx_oversize_errors", offsetof(struct e1000_hw_stats, roc),
+			RX_GROUP | ERR_GROUP},
+	{"rx_jabber_errors", offsetof(struct e1000_hw_stats, rjc),
+			RX_GROUP | ERR_GROUP},
+	{"rx_management_packets", offsetof(struct e1000_hw_stats, mgprc),
+			RX_GROUP},
+	{"rx_management_dropped", offsetof(struct e1000_hw_stats, mgpdc),
+			RX_GROUP},
+	{"tx_management_packets", offsetof(struct e1000_hw_stats, mgptc),
+			TX_GROUP},
+	{"rx_total_packets", offsetof(struct e1000_hw_stats, tpr),
+			RX_GROUP},
+	{"tx_total_packets", offsetof(struct e1000_hw_stats, tpt),
+			TX_GROUP},
+	{"rx_total_bytes", offsetof(struct e1000_hw_stats, tor),
+			RX_GROUP},
+	{"tx_total_bytes", offsetof(struct e1000_hw_stats, tot),
+			TX_GROUP},
+	{"tx_size_64_packets", offsetof(struct e1000_hw_stats, ptc64),
+			TX_GROUP},
+	{"tx_size_65_to_127_packets", offsetof(struct e1000_hw_stats, ptc127),
+			TX_GROUP},
+	{"tx_size_128_to_255_packets", offsetof(struct e1000_hw_stats, ptc255),
+			TX_GROUP},
+	{"tx_size_256_to_511_packets", offsetof(struct e1000_hw_stats, ptc511),
+			TX_GROUP},
 	{"tx_size_512_to_1023_packets", offsetof(struct e1000_hw_stats,
-		ptc1023)},
+		ptc1023), TX_GROUP},
 	{"tx_size_1023_to_max_packets", offsetof(struct e1000_hw_stats,
-		ptc1522)},
-	{"tx_multicast_packets", offsetof(struct e1000_hw_stats, mptc)},
-	{"tx_broadcast_packets", offsetof(struct e1000_hw_stats, bptc)},
-	{"tx_tso_packets", offsetof(struct e1000_hw_stats, tsctc)},
-	{"tx_tso_errors", offsetof(struct e1000_hw_stats, tsctfc)},
-	{"rx_sent_to_host_packets", offsetof(struct e1000_hw_stats, rpthc)},
-	{"tx_sent_by_host_packets", offsetof(struct e1000_hw_stats, hgptc)},
-	{"rx_code_violation_packets", offsetof(struct e1000_hw_stats, scvpc)},
-
-	{"interrupt_assert_count", offsetof(struct e1000_hw_stats, iac)},
+		ptc1522), TX_GROUP},
+	{"tx_multicast_packets", offsetof(struct e1000_hw_stats, mptc),
+			TX_GROUP},
+	{"tx_broadcast_packets", offsetof(struct e1000_hw_stats, bptc),
+			TX_GROUP},
+	{"tx_tso_packets", offsetof(struct e1000_hw_stats, tsctc),
+			TX_GROUP},
+	{"tx_tso_errors", offsetof(struct e1000_hw_stats, tsctfc),
+			TX_GROUP | ERR_GROUP},
+	{"rx_sent_to_host_packets", offsetof(struct e1000_hw_stats, rpthc),
+			RX_GROUP},
+	{"tx_sent_by_host_packets", offsetof(struct e1000_hw_stats, hgptc),
+			TX_GROUP},
+	{"rx_code_violation_packets", offsetof(struct e1000_hw_stats, scvpc),
+			TX_GROUP},
+	{"interrupt_assert_count", offsetof(struct e1000_hw_stats, iac),
+			RX_GROUP},
 };
 
 #define IGB_NB_XSTATS (sizeof(rte_igb_stats_strings) / \
 		sizeof(rte_igb_stats_strings[0]))
 
 static const struct rte_igb_xstats_name_off rte_igbvf_stats_strings[] = {
-	{"rx_multicast_packets", offsetof(struct e1000_vf_stats, mprc)},
-	{"rx_good_loopback_packets", offsetof(struct e1000_vf_stats, gprlbc)},
-	{"tx_good_loopback_packets", offsetof(struct e1000_vf_stats, gptlbc)},
-	{"rx_good_loopback_bytes", offsetof(struct e1000_vf_stats, gorlbc)},
-	{"tx_good_loopback_bytes", offsetof(struct e1000_vf_stats, gotlbc)},
+	{"rx_multicast_packets", offsetof(struct e1000_vf_stats, mprc),
+			RX_GROUP | VF_GROUP},
+	{"rx_good_loopback_packets", offsetof(struct e1000_vf_stats, gprlbc),
+			RX_GROUP | VF_GROUP},
+	{"tx_good_loopback_packets", offsetof(struct e1000_vf_stats, gptlbc),
+			TX_GROUP | VF_GROUP},
+	{"rx_good_loopback_bytes", offsetof(struct e1000_vf_stats, gorlbc),
+			RX_GROUP | VF_GROUP},
+	{"tx_good_loopback_bytes", offsetof(struct e1000_vf_stats, gotlbc),
+			TX_GROUP | VF_GROUP},
 };
 
 #define IGBVF_NB_XSTATS (sizeof(rte_igbvf_stats_strings) / \
@@ -1771,6 +1832,13 @@ struct rte_igb_xstats_name_off {
 	stats->cexterr += E1000_READ_REG(hw, E1000_CEXTERR);
 	stats->tsctc += E1000_READ_REG(hw, E1000_TSCTC);
 	stats->tsctfc += E1000_READ_REG(hw, E1000_TSCTFC);
+
+	if (hw->mac.type == e1000_i350 || hw->mac.type == e1000_i210) {
+		stats->o2bgptc += E1000_READ_REG(hw, E1000_O2BGPTC);
+		stats->o2bspc += E1000_READ_REG(hw, E1000_O2BSPC);
+		stats->b2ospc += E1000_READ_REG(hw, E1000_B2OSPC);
+		stats->b2ogprc += E1000_READ_REG(hw, E1000_B2OGPRC);
+	}
 }
 
 static void
@@ -1846,10 +1914,43 @@ 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_xstat *xstats,
-		   unsigned n)
+eth_igb_xstats_get_names_by_group(__rte_unused struct rte_eth_dev *dev,
+	struct rte_eth_xstat_name *xstats_names,
+	__rte_unused unsigned limit,
+	uint64_t group_mask)
 {
-	struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	unsigned i;
+	unsigned count = 0;
+
+	if (xstats_names == NULL) {
+		for (i = 0; i < IGB_NB_XSTATS; i++) {
+			if (rte_igb_stats_strings[i].group_mask & group_mask)
+				count++;
+		}
+		return count;
+	}
+
+	/* Note: limit checked in rte_eth_xstats_names() */
+
+	count = 0;
+	for (i = 0; i < IGB_NB_XSTATS; i++) {
+		if (rte_igb_stats_strings[i].group_mask & group_mask) {
+			snprintf(xstats_names[count].name,
+					sizeof(xstats_names[0].name),
+				 "%s", rte_igb_stats_strings[i].name);
+			count++;
+		}
+	}
+	return count;
+}
+
+static
+int 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);
 	struct e1000_hw_stats *hw_stats =
 			E1000_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
 	unsigned i;
@@ -1875,8 +1976,50 @@ static int eth_igb_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 	return IGB_NB_XSTATS;
 }
 
+static
+int eth_igb_xstats_get_by_group(struct rte_eth_dev *dev,
+		struct rte_eth_xstat *xstats,
+		unsigned n, uint64_t group_mask)
+{
+	struct e1000_hw *hw =
+			E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct e1000_hw_stats *hw_stats =
+			E1000_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+	unsigned i;
+	unsigned count = 0;
+
+
+	for (i = 0; i < IGB_NB_XSTATS; i++) {
+		if (rte_igb_stats_strings[i].group_mask & group_mask)
+			count++;
+	}
+
+	if (n < IGB_NB_XSTATS)
+		return count;
+
+	igb_read_stats_registers(hw, hw_stats);
+
+	/* If this is a reset xstats is NULL, and we have cleared the
+	 * registers by reading them.
+	 */
+	if (!xstats)
+		return 0;
+
+	/* Extended stats */
+	for (i = 0; i < IGB_NB_XSTATS; i++) {
+		if (rte_igb_stats_strings[i].group_mask & group_mask) {
+			xstats[i].id = i;
+			xstats[i].value = *(uint64_t *)(((char *)hw_stats) +
+				rte_igb_stats_strings[i].offset);
+		}
+	}
+
+	return count;
+}
+
 static void
-igbvf_read_stats_registers(struct e1000_hw *hw, struct e1000_vf_stats *hw_stats)
+igbvf_read_stats_registers(struct e1000_hw *hw,
+		struct e1000_vf_stats *hw_stats)
 {
 	/* Good Rx packets, include VF loopback */
 	UPDATE_VF_STAT(E1000_VFGPRC,
@@ -2314,7 +2457,8 @@ static int eth_igbvf_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 
 	/* Let firmware know the driver has taken over */
 	ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
-	E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext | E1000_CTRL_EXT_DRV_LOAD);
+	E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext |
+			E1000_CTRL_EXT_DRV_LOAD);
 }
 
 /*
-- 
1.9.1

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

* [PATCH 3/4] net/ixgbe: add grouping of xstats for ixgbe driver
  2017-03-02 16:07 [PATCH 0/4] extend API to retriving xstats by group and xstats by name Kuba Kozak
  2017-03-02 16:07 ` [PATCH 1/4] ethdev: add retrieving " Kuba Kozak
  2017-03-02 16:07 ` [PATCH 2/4] net/e1000: add grouping of xstats for e1000 driver Kuba Kozak
@ 2017-03-02 16:07 ` Kuba Kozak
  2 siblings, 0 replies; 6+ messages in thread
From: Kuba Kozak @ 2017-03-02 16:07 UTC (permalink / raw)
  To: dev; +Cc: Jacek Piasecki, Kuba Kozak

From: Jacek Piasecki <jacekx.piasecki@intel.com>

This patch extends the 'rte_ixgbe_xstats_name_off' structure
with additional field 'group_mask'. For each xstats there is
now specified group (e.g. MAC_GROUP), one xstatistic can be in
several groups. To implement new functionality of retriving
xstats by group on driver level, there are two functions added:
ixgbe_dev_xstats_get_by_group() and ixgbe_dev_xstats_get_names_by_group()

Signed-off-by: Jacek Piasecki <jacekx.piasecki@intel.com>
Signed-off-by: Kuba Kozak <kubax.kozak@intel.com>
---
 drivers/net/ixgbe/ixgbe_ethdev.c | 586 +++++++++++++++++++++++++++++++--------
 1 file changed, 475 insertions(+), 111 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 7169007..31aa4e2 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -124,7 +124,8 @@
 
 #define IXGBEVF_PMD_NAME "rte_ixgbevf_pmd" /* PMD name */
 
-#define IXGBE_QUEUE_STAT_COUNTERS (sizeof(hw_stats->qprc) / sizeof(hw_stats->qprc[0]))
+#define IXGBE_QUEUE_STAT_COUNTERS (sizeof(hw_stats->qprc) \
+		/ sizeof(hw_stats->qprc[0]))
 
 #define IXGBE_HKEY_MAX_INDEX 10
 
@@ -187,12 +188,25 @@ 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_xstat *xstats, unsigned n);
+static int ixgbe_dev_xstats_get_by_group(struct rte_eth_dev *dev,
+		struct rte_eth_xstat *xstats,
+		unsigned n, uint64_t group_mask);
 static int ixgbevf_dev_xstats_get(struct rte_eth_dev *dev,
 				  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_xstats_get_by_name(struct rte_eth_dev *dev,
+		struct rte_eth_xstat_name *xstats_names,
+		struct rte_eth_xstat *xstat,
+		const char *name);
 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 ixgbe_dev_xstats_get_names_by_group(__rte_unused
+		struct rte_eth_dev *dev,
+		struct rte_eth_xstat_name *xstats_names,
+		unsigned limit,
+		uint64_t group_mask);
 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,
@@ -532,10 +546,13 @@ static int ixgbe_dev_udp_tunnel_port_del(struct rte_eth_dev *dev,
 	.link_update          = ixgbe_dev_link_update,
 	.stats_get            = ixgbe_dev_stats_get,
 	.xstats_get           = ixgbe_dev_xstats_get,
+	.xstats_get_by_name   = ixgbe_xstats_get_by_name,
+	.xstats_get_by_group  = ixgbe_dev_xstats_get_by_group,
 	.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,
+	.xstats_get_names_by_group = ixgbe_dev_xstats_get_names_by_group,
 	.fw_version_get       = ixgbe_fw_version_get,
 	.dev_infos_get        = ixgbe_dev_info_get,
 	.dev_supported_ptypes_get = ixgbe_dev_supported_ptypes_get,
@@ -653,87 +670,125 @@ static int ixgbe_dev_udp_tunnel_port_del(struct rte_eth_dev *dev,
 struct rte_ixgbe_xstats_name_off {
 	char name[RTE_ETH_XSTATS_NAME_SIZE];
 	unsigned offset;
+	uint64_t group_mask;
 };
 
 static const struct rte_ixgbe_xstats_name_off rte_ixgbe_stats_strings[] = {
-	{"rx_crc_errors", offsetof(struct ixgbe_hw_stats, crcerrs)},
-	{"rx_illegal_byte_errors", offsetof(struct ixgbe_hw_stats, illerrc)},
-	{"rx_error_bytes", offsetof(struct ixgbe_hw_stats, errbc)},
-	{"mac_local_errors", offsetof(struct ixgbe_hw_stats, mlfc)},
-	{"mac_remote_errors", offsetof(struct ixgbe_hw_stats, mrfc)},
-	{"rx_length_errors", offsetof(struct ixgbe_hw_stats, rlec)},
-	{"tx_xon_packets", offsetof(struct ixgbe_hw_stats, lxontxc)},
-	{"rx_xon_packets", offsetof(struct ixgbe_hw_stats, lxonrxc)},
-	{"tx_xoff_packets", offsetof(struct ixgbe_hw_stats, lxofftxc)},
-	{"rx_xoff_packets", offsetof(struct ixgbe_hw_stats, lxoffrxc)},
-	{"rx_size_64_packets", offsetof(struct ixgbe_hw_stats, prc64)},
-	{"rx_size_65_to_127_packets", offsetof(struct ixgbe_hw_stats, prc127)},
-	{"rx_size_128_to_255_packets", offsetof(struct ixgbe_hw_stats, prc255)},
-	{"rx_size_256_to_511_packets", offsetof(struct ixgbe_hw_stats, prc511)},
+	{"rx_crc_errors", offsetof(struct ixgbe_hw_stats, crcerrs),
+			RX_GROUP | ERR_GROUP},
+	{"rx_illegal_byte_errors",
+			offsetof(struct ixgbe_hw_stats, illerrc),
+			RX_GROUP | ERR_GROUP},
+	{"rx_error_bytes", offsetof(struct ixgbe_hw_stats, errbc),
+			RX_GROUP | ERR_GROUP},
+	{"mac_local_errors", offsetof(struct ixgbe_hw_stats, mlfc), ERR_GROUP},
+	{"mac_remote_errors", offsetof(struct ixgbe_hw_stats, mrfc), ERR_GROUP},
+	{"rx_length_errors", offsetof(struct ixgbe_hw_stats, rlec),
+			RX_GROUP | ERR_GROUP},
+	{"tx_xon_packets", offsetof(struct ixgbe_hw_stats, lxontxc), TX_GROUP},
+	{"rx_xon_packets", offsetof(struct ixgbe_hw_stats, lxonrxc), RX_GROUP},
+	{"tx_xoff_packets", offsetof(struct ixgbe_hw_stats, lxofftxc),
+			TX_GROUP},
+	{"rx_xoff_packets", offsetof(struct ixgbe_hw_stats, lxoffrxc),
+			RX_GROUP},
+	{"rx_size_64_packets", offsetof(struct ixgbe_hw_stats, prc64),
+			RX_GROUP},
+	{"rx_size_65_to_127_packets",
+			offsetof(struct ixgbe_hw_stats, prc127), RX_GROUP},
+	{"rx_size_128_to_255_packets",
+			offsetof(struct ixgbe_hw_stats, prc255), RX_GROUP},
+	{"rx_size_256_to_511_packets",
+			offsetof(struct ixgbe_hw_stats, prc511), RX_GROUP},
 	{"rx_size_512_to_1023_packets", offsetof(struct ixgbe_hw_stats,
-		prc1023)},
+		prc1023), RX_GROUP},
 	{"rx_size_1024_to_max_packets", offsetof(struct ixgbe_hw_stats,
-		prc1522)},
-	{"rx_broadcast_packets", offsetof(struct ixgbe_hw_stats, bprc)},
-	{"rx_multicast_packets", offsetof(struct ixgbe_hw_stats, mprc)},
-	{"rx_fragment_errors", offsetof(struct ixgbe_hw_stats, rfc)},
-	{"rx_undersize_errors", offsetof(struct ixgbe_hw_stats, ruc)},
-	{"rx_oversize_errors", offsetof(struct ixgbe_hw_stats, roc)},
-	{"rx_jabber_errors", offsetof(struct ixgbe_hw_stats, rjc)},
-	{"rx_management_packets", offsetof(struct ixgbe_hw_stats, mngprc)},
-	{"rx_management_dropped", offsetof(struct ixgbe_hw_stats, mngpdc)},
-	{"tx_management_packets", offsetof(struct ixgbe_hw_stats, mngptc)},
-	{"rx_total_packets", offsetof(struct ixgbe_hw_stats, tpr)},
-	{"rx_total_bytes", offsetof(struct ixgbe_hw_stats, tor)},
-	{"tx_total_packets", offsetof(struct ixgbe_hw_stats, tpt)},
-	{"tx_size_64_packets", offsetof(struct ixgbe_hw_stats, ptc64)},
-	{"tx_size_65_to_127_packets", offsetof(struct ixgbe_hw_stats, ptc127)},
-	{"tx_size_128_to_255_packets", offsetof(struct ixgbe_hw_stats, ptc255)},
-	{"tx_size_256_to_511_packets", offsetof(struct ixgbe_hw_stats, ptc511)},
-	{"tx_size_512_to_1023_packets", offsetof(struct ixgbe_hw_stats,
-		ptc1023)},
+		prc1522), RX_GROUP},
+	{"rx_broadcast_packets", offsetof(struct ixgbe_hw_stats, bprc),
+			RX_GROUP},
+	{"rx_multicast_packets", offsetof(struct ixgbe_hw_stats, mprc),
+			RX_GROUP},
+	{"rx_fragment_errors", offsetof(struct ixgbe_hw_stats, rfc),
+			RX_GROUP | ERR_GROUP},
+	{"rx_undersize_errors", offsetof(struct ixgbe_hw_stats, ruc),
+			RX_GROUP | ERR_GROUP},
+	{"rx_oversize_errors", offsetof(struct ixgbe_hw_stats, roc),
+			RX_GROUP | ERR_GROUP},
+	{"rx_jabber_errors", offsetof(struct ixgbe_hw_stats, rjc),
+			RX_GROUP | ERR_GROUP},
+	{"rx_management_packets", offsetof(struct ixgbe_hw_stats, mngprc),
+			RX_GROUP},
+	{"rx_management_dropped", offsetof(struct ixgbe_hw_stats, mngpdc),
+			RX_GROUP},
+	{"tx_management_packets", offsetof(struct ixgbe_hw_stats, mngptc),
+			TX_GROUP},
+	{"rx_total_packets", offsetof(struct ixgbe_hw_stats, tpr), RX_GROUP},
+	{"rx_total_bytes", offsetof(struct ixgbe_hw_stats, tor), RX_GROUP},
+	{"tx_total_packets", offsetof(struct ixgbe_hw_stats, tpt), TX_GROUP},
+	{"tx_size_64_packets", offsetof(struct ixgbe_hw_stats, ptc64),
+			TX_GROUP},
+	{"tx_size_65_to_127_packets",
+			offsetof(struct ixgbe_hw_stats, ptc127), TX_GROUP},
+	{"tx_size_128_to_255_packets",
+			offsetof(struct ixgbe_hw_stats, ptc255), TX_GROUP},
+	{"tx_size_256_to_511_packets",
+			offsetof(struct ixgbe_hw_stats, ptc511), TX_GROUP},
+	{"tx_size_512_to_1023_packets",
+			offsetof(struct ixgbe_hw_stats,
+		ptc1023), TX_GROUP},
 	{"tx_size_1024_to_max_packets", offsetof(struct ixgbe_hw_stats,
-		ptc1522)},
-	{"tx_multicast_packets", offsetof(struct ixgbe_hw_stats, mptc)},
-	{"tx_broadcast_packets", offsetof(struct ixgbe_hw_stats, bptc)},
-	{"rx_mac_short_packet_dropped", offsetof(struct ixgbe_hw_stats, mspdc)},
-	{"rx_l3_l4_xsum_error", offsetof(struct ixgbe_hw_stats, xec)},
-
+		ptc1522), TX_GROUP},
+	{"tx_multicast_packets", offsetof(struct ixgbe_hw_stats, mptc),
+			TX_GROUP},
+	{"tx_broadcast_packets", offsetof(struct ixgbe_hw_stats, bptc),
+			TX_GROUP},
+	{"rx_mac_short_packet_dropped",
+			offsetof(struct ixgbe_hw_stats, mspdc), RX_GROUP},
+	{"rx_l3_l4_xsum_error", offsetof(struct ixgbe_hw_stats, xec),
+			RX_GROUP | ERR_GROUP},
 	{"flow_director_added_filters", offsetof(struct ixgbe_hw_stats,
-		fdirustat_add)},
+		fdirustat_add), 0},
 	{"flow_director_removed_filters", offsetof(struct ixgbe_hw_stats,
-		fdirustat_remove)},
+		fdirustat_remove), 0},
 	{"flow_director_filter_add_errors", offsetof(struct ixgbe_hw_stats,
-		fdirfstat_fadd)},
+		fdirfstat_fadd), ERR_GROUP},
 	{"flow_director_filter_remove_errors", offsetof(struct ixgbe_hw_stats,
-		fdirfstat_fremove)},
+		fdirfstat_fremove), ERR_GROUP},
 	{"flow_director_matched_filters", offsetof(struct ixgbe_hw_stats,
-		fdirmatch)},
+		fdirmatch), 0},
 	{"flow_director_missed_filters", offsetof(struct ixgbe_hw_stats,
-		fdirmiss)},
+		fdirmiss), 0},
 
-	{"rx_fcoe_crc_errors", offsetof(struct ixgbe_hw_stats, fccrc)},
-	{"rx_fcoe_dropped", offsetof(struct ixgbe_hw_stats, fcoerpdc)},
+	{"rx_fcoe_crc_errors", offsetof(struct ixgbe_hw_stats, fccrc),
+			RX_GROUP | ERR_GROUP},
+	{"rx_fcoe_dropped", offsetof(struct ixgbe_hw_stats, fcoerpdc),
+			RX_GROUP},
 	{"rx_fcoe_mbuf_allocation_errors", offsetof(struct ixgbe_hw_stats,
-		fclast)},
-	{"rx_fcoe_packets", offsetof(struct ixgbe_hw_stats, fcoeprc)},
-	{"tx_fcoe_packets", offsetof(struct ixgbe_hw_stats, fcoeptc)},
-	{"rx_fcoe_bytes", offsetof(struct ixgbe_hw_stats, fcoedwrc)},
-	{"tx_fcoe_bytes", offsetof(struct ixgbe_hw_stats, fcoedwtc)},
+		fclast), RX_GROUP | ERR_GROUP},
+	{"rx_fcoe_packets", offsetof(struct ixgbe_hw_stats, fcoeprc), RX_GROUP},
+	{"tx_fcoe_packets", offsetof(struct ixgbe_hw_stats, fcoeptc), TX_GROUP},
+	{"rx_fcoe_bytes", offsetof(struct ixgbe_hw_stats, fcoedwrc), RX_GROUP},
+	{"tx_fcoe_bytes", offsetof(struct ixgbe_hw_stats, fcoedwtc), TX_GROUP},
 	{"rx_fcoe_no_direct_data_placement", offsetof(struct ixgbe_hw_stats,
-		fcoe_noddp)},
+		fcoe_noddp), RX_GROUP},
 	{"rx_fcoe_no_direct_data_placement_ext_buff",
-		offsetof(struct ixgbe_hw_stats, fcoe_noddp_ext_buff)},
-
+		offsetof(struct ixgbe_hw_stats, fcoe_noddp_ext_buff), RX_GROUP},
 	{"tx_flow_control_xon_packets", offsetof(struct ixgbe_hw_stats,
-		lxontxc)},
+		lxontxc), TX_GROUP},
 	{"rx_flow_control_xon_packets", offsetof(struct ixgbe_hw_stats,
-		lxonrxc)},
+		lxonrxc), RX_GROUP},
 	{"tx_flow_control_xoff_packets", offsetof(struct ixgbe_hw_stats,
-		lxofftxc)},
+		lxofftxc), TX_GROUP},
 	{"rx_flow_control_xoff_packets", offsetof(struct ixgbe_hw_stats,
-		lxoffrxc)},
-	{"rx_total_missed_packets", offsetof(struct ixgbe_hw_stats, mpctotal)},
+		lxoffrxc), RX_GROUP},
+	{"rx_total_missed_packets",
+			offsetof(struct ixgbe_hw_stats, mpctotal), RX_GROUP},
+	{"os2bmc_rx_by_bmc", offsetof(struct ixgbe_hw_stats, o2bgptc),
+			RX_GROUP},
+	{"os2bmc_tx_by_bmc", offsetof(struct ixgbe_hw_stats, b2ospc), TX_GROUP},
+	{"os2bmc_tx_by_host", offsetof(struct ixgbe_hw_stats, o2bspc),
+			TX_GROUP},
+	{"os2bmc_rx_by_host", offsetof(struct ixgbe_hw_stats, b2ogprc),
+			RX_GROUP},
 };
 
 #define IXGBE_NB_HW_STATS (sizeof(rte_ixgbe_stats_strings) / \
@@ -742,43 +797,43 @@ struct rte_ixgbe_xstats_name_off {
 /* MACsec statistics */
 static const struct rte_ixgbe_xstats_name_off rte_ixgbe_macsec_strings[] = {
 	{"out_pkts_untagged", offsetof(struct ixgbe_macsec_stats,
-		out_pkts_untagged)},
+		out_pkts_untagged), MAC_GROUP},
 	{"out_pkts_encrypted", offsetof(struct ixgbe_macsec_stats,
-		out_pkts_encrypted)},
+		out_pkts_encrypted), MAC_GROUP},
 	{"out_pkts_protected", offsetof(struct ixgbe_macsec_stats,
-		out_pkts_protected)},
+		out_pkts_protected), MAC_GROUP},
 	{"out_octets_encrypted", offsetof(struct ixgbe_macsec_stats,
-		out_octets_encrypted)},
+		out_octets_encrypted), MAC_GROUP},
 	{"out_octets_protected", offsetof(struct ixgbe_macsec_stats,
-		out_octets_protected)},
+		out_octets_protected), MAC_GROUP},
 	{"in_pkts_untagged", offsetof(struct ixgbe_macsec_stats,
-		in_pkts_untagged)},
+		in_pkts_untagged), MAC_GROUP},
 	{"in_pkts_badtag", offsetof(struct ixgbe_macsec_stats,
-		in_pkts_badtag)},
+		in_pkts_badtag), MAC_GROUP},
 	{"in_pkts_nosci", offsetof(struct ixgbe_macsec_stats,
-		in_pkts_nosci)},
+		in_pkts_nosci), MAC_GROUP},
 	{"in_pkts_unknownsci", offsetof(struct ixgbe_macsec_stats,
-		in_pkts_unknownsci)},
+		in_pkts_unknownsci), MAC_GROUP},
 	{"in_octets_decrypted", offsetof(struct ixgbe_macsec_stats,
-		in_octets_decrypted)},
+		in_octets_decrypted), MAC_GROUP},
 	{"in_octets_validated", offsetof(struct ixgbe_macsec_stats,
-		in_octets_validated)},
+		in_octets_validated), MAC_GROUP},
 	{"in_pkts_unchecked", offsetof(struct ixgbe_macsec_stats,
-		in_pkts_unchecked)},
+		in_pkts_unchecked), MAC_GROUP},
 	{"in_pkts_delayed", offsetof(struct ixgbe_macsec_stats,
-		in_pkts_delayed)},
+		in_pkts_delayed), MAC_GROUP},
 	{"in_pkts_late", offsetof(struct ixgbe_macsec_stats,
-		in_pkts_late)},
+		in_pkts_late), MAC_GROUP},
 	{"in_pkts_ok", offsetof(struct ixgbe_macsec_stats,
-		in_pkts_ok)},
+		in_pkts_ok), MAC_GROUP},
 	{"in_pkts_invalid", offsetof(struct ixgbe_macsec_stats,
-		in_pkts_invalid)},
+		in_pkts_invalid), MAC_GROUP},
 	{"in_pkts_notvalid", offsetof(struct ixgbe_macsec_stats,
-		in_pkts_notvalid)},
+		in_pkts_notvalid), MAC_GROUP},
 	{"in_pkts_unusedsa", offsetof(struct ixgbe_macsec_stats,
-		in_pkts_unusedsa)},
+		in_pkts_unusedsa), MAC_GROUP},
 	{"in_pkts_notusingsa", offsetof(struct ixgbe_macsec_stats,
-		in_pkts_notusingsa)},
+		in_pkts_notusingsa), MAC_GROUP},
 };
 
 #define IXGBE_NB_MACSEC_STATS (sizeof(rte_ixgbe_macsec_strings) / \
@@ -786,10 +841,11 @@ struct rte_ixgbe_xstats_name_off {
 
 /* Per-queue statistics */
 static const struct rte_ixgbe_xstats_name_off rte_ixgbe_rxq_strings[] = {
-	{"mbuf_allocation_errors", offsetof(struct ixgbe_hw_stats, rnbc)},
-	{"dropped", offsetof(struct ixgbe_hw_stats, mpc)},
-	{"xon_packets", offsetof(struct ixgbe_hw_stats, pxonrxc)},
-	{"xoff_packets", offsetof(struct ixgbe_hw_stats, pxoffrxc)},
+	{"mbuf_allocation_errors", offsetof(struct ixgbe_hw_stats, rnbc),
+			ERR_GROUP | RXQ_GROUP},
+	{"dropped", offsetof(struct ixgbe_hw_stats, mpc), RXQ_GROUP},
+	{"xon_packets", offsetof(struct ixgbe_hw_stats, pxonrxc), RXQ_GROUP},
+	{"xoff_packets", offsetof(struct ixgbe_hw_stats, pxoffrxc), RXQ_GROUP},
 };
 
 #define IXGBE_NB_RXQ_PRIO_STATS (sizeof(rte_ixgbe_rxq_strings) / \
@@ -797,10 +853,10 @@ struct rte_ixgbe_xstats_name_off {
 #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)},
-	{"xoff_packets", offsetof(struct ixgbe_hw_stats, pxofftxc)},
+	{"xon_packets", offsetof(struct ixgbe_hw_stats, pxontxc), TXQ_GROUP},
+	{"xoff_packets", offsetof(struct ixgbe_hw_stats, pxofftxc), TXQ_GROUP},
 	{"xon_to_xoff_packets", offsetof(struct ixgbe_hw_stats,
-		pxon2offc)},
+		pxon2offc), TXQ_GROUP},
 };
 
 #define IXGBE_NB_TXQ_PRIO_STATS (sizeof(rte_ixgbe_txq_strings) / \
@@ -808,7 +864,8 @@ struct rte_ixgbe_xstats_name_off {
 #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)},
+	{"rx_multicast_packets",
+			offsetof(struct ixgbevf_hw_stats, vfmprc), RX_GROUP},
 };
 
 #define IXGBEVF_NB_XSTATS (sizeof(rte_ixgbevf_stats_strings) /	\
@@ -2414,8 +2471,9 @@ static int ixgbe_l2_tn_filter_init(struct rte_eth_dev *eth_dev)
 	*    - fixed speed: TODO implement
 	*/
 	if (dev->data->dev_conf.link_speeds & ETH_LINK_SPEED_FIXED) {
-		PMD_INIT_LOG(ERR, "Invalid link_speeds for port %hhu; fix speed not supported",
-			     dev->data->port_id);
+		PMD_INIT_LOG(ERR,
+				"Invalid link_speeds for port %hhu; fix speed not supported",
+				dev->data->port_id);
 		return -EINVAL;
 	}
 
@@ -2882,18 +2940,41 @@ static int ixgbe_l2_tn_filter_init(struct rte_eth_dev *eth_dev)
 	hw_stats->prc1023 += IXGBE_READ_REG(hw, IXGBE_PRC1023);
 	hw_stats->prc1522 += IXGBE_READ_REG(hw, IXGBE_PRC1522);
 
-	lxon = IXGBE_READ_REG(hw, IXGBE_LXONTXC);
-	hw_stats->lxontxc += lxon;
-	lxoff = IXGBE_READ_REG(hw, IXGBE_LXOFFTXC);
-	hw_stats->lxofftxc += lxoff;
-	total = lxon + lxoff;
+	switch (hw->mac.type) {
+	case ixgbe_mac_82599EB:
+	case ixgbe_mac_82598EB:
+		lxon = IXGBE_READ_REG(hw, IXGBE_LXONTXC);
+		hw_stats->lxontxc += lxon;
+		lxoff = IXGBE_READ_REG(hw, IXGBE_LXOFFTXC);
+		hw_stats->lxofftxc += lxoff;
+		total = lxon + lxoff;
+		hw_stats->mptc += IXGBE_READ_REG(hw, IXGBE_MPTC);
+		hw_stats->ptc64 += IXGBE_READ_REG(hw, IXGBE_PTC64);
+		hw_stats->gptc -= total;
+		hw_stats->mptc -= total;
+		hw_stats->ptc64 -= total;
+		hw_stats->gotc -= total * ETHER_MIN_LEN;
+		break;
+	case ixgbe_mac_X540:
+	case ixgbe_mac_X550:
+		lxon = IXGBE_READ_REG(hw, IXGBE_BXONTXC);
+		hw_stats->lxontxc += lxon;
+		lxoff = IXGBE_READ_REG(hw, IXGBE_BXOFFTXC);
+		hw_stats->lxofftxc += lxoff;
+		total = lxon + lxoff;
+		hw_stats->mptc += IXGBE_READ_REG(hw, IXGBE_MPTC);
+		hw_stats->ptc64 += IXGBE_READ_REG(hw, IXGBE_PTC64);
+		hw_stats->gptc -= total;
+		hw_stats->mptc -= total;
+		hw_stats->ptc64 -= total;
+		hw_stats->gotc -= total * ETHER_MIN_LEN;
+		break;
+	default:
+		break;
+	}
+
+
 
-	hw_stats->mptc += IXGBE_READ_REG(hw, IXGBE_MPTC);
-	hw_stats->ptc64 += IXGBE_READ_REG(hw, IXGBE_PTC64);
-	hw_stats->gptc -= total;
-	hw_stats->mptc -= total;
-	hw_stats->ptc64 -= total;
-	hw_stats->gotc -= total * ETHER_MIN_LEN;
 
 	hw_stats->ruc += IXGBE_READ_REG(hw, IXGBE_RUC);
 	hw_stats->rfc += IXGBE_READ_REG(hw, IXGBE_RFC);
@@ -2911,18 +2992,43 @@ static int ixgbe_l2_tn_filter_init(struct rte_eth_dev *eth_dev)
 	hw_stats->xec += IXGBE_READ_REG(hw, IXGBE_XEC);
 	hw_stats->fccrc += IXGBE_READ_REG(hw, IXGBE_FCCRC);
 	hw_stats->fclast += IXGBE_READ_REG(hw, IXGBE_FCLAST);
-	/* Only read FCOE on 82599 */
-	if (hw->mac.type != ixgbe_mac_82598EB) {
-		hw_stats->fcoerpdc += IXGBE_READ_REG(hw, IXGBE_FCOERPDC);
-		hw_stats->fcoeprc += IXGBE_READ_REG(hw, IXGBE_FCOEPRC);
+
+	switch (hw->mac.type) {
+	case ixgbe_mac_X540:
+	case ixgbe_mac_X550:
+		hw_stats->o2bgptc += IXGBE_READ_REG(hw, IXGBE_O2BGPTC);
+		hw_stats->o2bspc += IXGBE_READ_REG(hw, IXGBE_O2BSPC);
+		hw_stats->b2ospc += IXGBE_READ_REG(hw, IXGBE_B2OSPC);
+		hw_stats->b2ogprc += IXGBE_READ_REG(hw, IXGBE_B2OGPRC);
+		hw_stats->fcoedwrc += IXGBE_READ_REG(hw, IXGBE_FCOEDWRC);
+		hw_stats->fcoedwtc += IXGBE_READ_REG(hw, IXGBE_FCOEDWTC);
 		hw_stats->fcoeptc += IXGBE_READ_REG(hw, IXGBE_FCOEPTC);
+		hw_stats->fcoeprc += IXGBE_READ_REG(hw, IXGBE_FCOEPRC);
+		hw_stats->fcoerpdc += IXGBE_READ_REG(hw, IXGBE_FCOERPDC);
+		/* Flow Director Stats registers */
+		hw_stats->fdirmatch += IXGBE_READ_REG(hw, IXGBE_FDIRMATCH);
+		hw_stats->fdirmiss += IXGBE_READ_REG(hw, IXGBE_FDIRMISS);
+		break;
+
+	case ixgbe_mac_82599EB:
 		hw_stats->fcoedwrc += IXGBE_READ_REG(hw, IXGBE_FCOEDWRC);
 		hw_stats->fcoedwtc += IXGBE_READ_REG(hw, IXGBE_FCOEDWTC);
+		hw_stats->fcoeptc += IXGBE_READ_REG(hw, IXGBE_FCOEPTC);
+		hw_stats->fcoeprc += IXGBE_READ_REG(hw, IXGBE_FCOEPRC);
+		hw_stats->fcoerpdc += IXGBE_READ_REG(hw, IXGBE_FCOERPDC);
+		/* Flow Director Stats registers */
+		hw_stats->fdirmatch += IXGBE_READ_REG(hw, IXGBE_FDIRMATCH);
+		hw_stats->fdirmiss += IXGBE_READ_REG(hw, IXGBE_FDIRMISS);
+		break;
+
+	case ixgbe_mac_82598EB:
+		break;
+
+	default:
+		break;
 	}
 
-	/* Flow Director Stats registers */
-	hw_stats->fdirmatch += IXGBE_READ_REG(hw, IXGBE_FDIRMATCH);
-	hw_stats->fdirmiss += IXGBE_READ_REG(hw, IXGBE_FDIRMISS);
+
 
 	/* MACsec Stats registers */
 	macsec_stats->out_pkts_untagged += IXGBE_READ_REG(hw, IXGBE_LSECTXUT);
@@ -3038,6 +3144,104 @@ static int ixgbe_l2_tn_filter_init(struct rte_eth_dev *eth_dev)
 		(IXGBE_NB_TXQ_PRIO_STATS * IXGBE_NB_TXQ_PRIO_VALUES);
 }
 
+static unsigned
+ixgbe_xstats_calc_num_by_group(uint64_t group_mask) {
+	unsigned i;
+	unsigned count = 0;
+
+	for (i = 0; i < IXGBE_NB_HW_STATS; i++) {
+		if (rte_ixgbe_stats_strings[i].group_mask & group_mask)
+			count++;
+	}
+	for (i = 0; i < IXGBE_NB_MACSEC_STATS; i++) {
+		if (rte_ixgbe_macsec_strings[i].group_mask & group_mask)
+			count++;
+	}
+	for (i = 0; i < IXGBE_NB_RXQ_PRIO_STATS; i++) {
+		if (rte_ixgbe_rxq_strings[i].group_mask & group_mask)
+			count += IXGBE_NB_TXQ_PRIO_VALUES;
+	}
+	for (i = 0; i < IXGBE_NB_TXQ_PRIO_STATS; i++) {
+		if (rte_ixgbe_txq_strings[i].group_mask & group_mask)
+			count += IXGBE_NB_TXQ_PRIO_VALUES;
+	}
+
+	return count;
+}
+
+static int ixgbe_xstats_get_by_name(struct rte_eth_dev *dev,
+		struct rte_eth_xstat_name *xstats_names,
+		struct rte_eth_xstat *xstat,
+		const char *name)
+{
+	struct ixgbe_hw_stats *hw_stats =
+			IXGBE_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+
+	unsigned i;
+
+
+	const unsigned cnt_stats = ixgbe_xstats_calc_num();
+	if (xstats_names == NULL)
+		return cnt_stats;
+
+	unsigned current = 0;
+
+	for (i = 0; i < IXGBE_NB_HW_STATS; i++) {
+		if (!strncmp(rte_ixgbe_stats_strings[i].name, name,
+				sizeof(rte_ixgbe_stats_strings[i].name))) {
+			snprintf(xstats_names[current].name,
+					sizeof(xstats_names[current].name),
+					"%s", rte_ixgbe_stats_strings[i].name);
+			xstat[current].id = current;
+			xstat[current].value =
+					*(uint64_t *)(((char *)hw_stats) +
+					rte_ixgbe_stats_strings[i].offset);
+			break;
+		};
+	}
+	for (i = 0; i < IXGBE_NB_MACSEC_STATS; i++) {
+		if (!strncmp(rte_ixgbe_macsec_strings[i].name, name,
+				sizeof(rte_ixgbe_macsec_strings[i].name))) {
+			snprintf(xstats_names[current].name,
+					sizeof(xstats_names[current].name),
+					"%s",
+					rte_ixgbe_macsec_strings[i].name);
+			xstat[current].id = current;
+			xstat[current].value =
+					*(uint64_t *)(((char *)hw_stats) +
+					rte_ixgbe_macsec_strings[i].offset);
+			break;
+		};
+	}
+	for (i = 0; i < IXGBE_NB_RXQ_PRIO_STATS; i++) {
+		if (!strncmp(rte_ixgbe_rxq_strings[i].name, name,
+				sizeof(rte_ixgbe_rxq_strings[i].name))) {
+			snprintf(xstats_names[current].name,
+					sizeof(xstats_names[current].name),
+					"%s", rte_ixgbe_rxq_strings[i].name);
+			xstat[current].id = current;
+			xstat[current].value =
+					*(uint64_t *)(((char *)hw_stats) +
+					rte_ixgbe_rxq_strings[i].offset);
+			break;
+		};
+	}
+	for (i = 0; i < IXGBE_NB_TXQ_PRIO_STATS; i++) {
+		if (!strncmp(rte_ixgbe_txq_strings[i].name, name,
+				sizeof(rte_ixgbe_txq_strings[i].name))) {
+			snprintf(xstats_names[current].name,
+					sizeof(xstats_names[current].name),
+					"%s", rte_ixgbe_txq_strings[i].name);
+			xstat[current].id = current;
+			xstat[current].value =
+					*(uint64_t *)(((char *)hw_stats) +
+					rte_ixgbe_txq_strings[i].offset);
+			break;
+		};
+	}
+	return cnt_stats;
+}
+
 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)
 {
@@ -3094,6 +3298,76 @@ static int ixgbe_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 	return cnt_stats;
 }
 
+static
+int ixgbe_dev_xstats_get_names_by_group(__rte_unused struct rte_eth_dev *dev,
+	struct rte_eth_xstat_name *xstats_names,
+	__rte_unused unsigned limit, uint64_t group_mask)
+{
+	const unsigned cnt_stats = ixgbe_xstats_calc_num_by_group(group_mask);
+	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++) {
+			if (rte_ixgbe_stats_strings[i].group_mask &
+					group_mask)	{
+				snprintf(xstats_names[count].name,
+					sizeof(xstats_names[count].name),
+					"%s",
+					rte_ixgbe_stats_strings[i].name);
+				count++;
+			}
+		}
+
+		/* MACsec Stats */
+		for (i = 0; i < IXGBE_NB_MACSEC_STATS; i++) {
+			if (rte_ixgbe_macsec_strings[i].group_mask &
+					group_mask){
+				snprintf(xstats_names[count].name,
+					sizeof(xstats_names[count].name),
+					"%s",
+					rte_ixgbe_macsec_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++) {
+				if (rte_ixgbe_rxq_strings[stat].group_mask &
+					    group_mask) {
+					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++) {
+				if (rte_ixgbe_txq_strings[stat].group_mask &
+					    group_mask) {
+					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)
 {
@@ -3184,6 +3458,94 @@ static int ixgbevf_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 	return count;
 }
 
+static int
+ixgbe_dev_xstats_get_by_group(struct rte_eth_dev *dev,
+		struct rte_eth_xstat *xstats,
+		unsigned n, uint64_t group_mask)
+{
+	struct ixgbe_hw *hw =
+			IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+	struct ixgbe_hw_stats *hw_stats =
+			IXGBE_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+	struct ixgbe_macsec_stats *macsec_stats =
+			IXGBE_DEV_PRIVATE_TO_MACSEC_STATS(
+				dev->data->dev_private);
+	uint64_t total_missed_rx, total_qbrc, total_qprc, total_qprdc;
+	unsigned i, stat, count = 0;
+
+	count = ixgbe_xstats_calc_num_by_group(group_mask);
+
+	if (n < count)
+		return count;
+
+	total_missed_rx = 0;
+	total_qbrc = 0;
+	total_qprc = 0;
+	total_qprdc = 0;
+
+	ixgbe_read_stats_registers(hw, hw_stats, macsec_stats, &total_missed_rx,
+			&total_qbrc, &total_qprc, &total_qprdc);
+
+	/* If this is a reset xstats is NULL, and we have cleared the
+	 * registers by reading them.
+	 */
+	if (!xstats)
+		return 0;
+
+	/* Extended stats from ixgbe_hw_stats */
+	count = 0;
+	for (i = 0; i < IXGBE_NB_HW_STATS; i++) {
+		if (rte_ixgbe_stats_strings[i].group_mask & group_mask) {
+			xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
+					rte_ixgbe_stats_strings[i].offset);
+			xstats[count].id = count;
+			count++;
+		}
+	}
+
+	/* MACsec Stats */
+	for (i = 0; i < IXGBE_NB_MACSEC_STATS; i++) {
+		if (rte_ixgbe_macsec_strings[i].group_mask & group_mask) {
+			xstats[count].value =
+					*(uint64_t *)(((char *)macsec_stats) +
+					rte_ixgbe_macsec_strings[i].offset);
+			xstats[count].id = count;
+			count++;
+		}
+	}
+
+	/* RX Priority Stats */
+	for (stat = 0; stat < IXGBE_NB_RXQ_PRIO_STATS; stat++) {
+		for (i = 0; i < IXGBE_NB_RXQ_PRIO_VALUES; i++) {
+			if (rte_ixgbe_rxq_strings[stat].group_mask &
+					group_mask) {
+				xstats[count].value =
+					*(uint64_t *)(((char *)hw_stats) +
+					rte_ixgbe_rxq_strings[stat].offset +
+					(sizeof(uint64_t) * i));
+				xstats[count].id = count;
+				count++;
+			}
+		}
+	}
+
+	/* TX Priority Stats */
+	for (stat = 0; stat < IXGBE_NB_TXQ_PRIO_STATS; stat++) {
+		for (i = 0; i < IXGBE_NB_TXQ_PRIO_VALUES; i++) {
+			if (rte_ixgbe_txq_strings[stat].group_mask &
+					group_mask) {
+				xstats[count].value =
+					*(uint64_t *)(((char *)hw_stats) +
+					rte_ixgbe_txq_strings[stat].offset +
+					(sizeof(uint64_t) * i));
+				xstats[count].id = count;
+				count++;
+			}
+		}
+	}
+	return count;
+}
+
 static void
 ixgbe_dev_xstats_reset(struct rte_eth_dev *dev)
 {
@@ -4097,7 +4459,8 @@ static int ixgbevf_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 
 	/* Disable any previous flow control settings */
 	mflcn_reg = IXGBE_READ_REG(hw, IXGBE_MFLCN);
-	mflcn_reg &= ~(IXGBE_MFLCN_RPFCE_SHIFT | IXGBE_MFLCN_RFCE|IXGBE_MFLCN_RPFCE);
+	mflcn_reg &= ~(IXGBE_MFLCN_RPFCE_SHIFT |
+			IXGBE_MFLCN_RFCE | IXGBE_MFLCN_RPFCE);
 
 	fccfg_reg = IXGBE_READ_REG(hw, IXGBE_FCCFG);
 	fccfg_reg &= ~(IXGBE_FCCFG_TFCE_802_3X | IXGBE_FCCFG_TFCE_PRIORITY);
@@ -4206,7 +4569,8 @@ static int ixgbevf_dev_xstats_get_names(__rte_unused struct rte_eth_dev *dev,
 }
 
 static int
-ixgbe_priority_flow_ctrl_set(struct rte_eth_dev *dev, struct rte_eth_pfc_conf *pfc_conf)
+ixgbe_priority_flow_ctrl_set(struct rte_eth_dev *dev,
+		struct rte_eth_pfc_conf *pfc_conf)
 {
 	int err;
 	uint32_t rx_buf_size;
-- 
1.9.1

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

* Re: [PATCH 2/4] net/e1000: add grouping of xstats for e1000 driver
  2017-03-02 16:07 ` [PATCH 2/4] net/e1000: add grouping of xstats for e1000 driver Kuba Kozak
@ 2017-03-03  1:35   ` Lu, Wenzhuo
  0 siblings, 0 replies; 6+ messages in thread
From: Lu, Wenzhuo @ 2017-03-03  1:35 UTC (permalink / raw)
  To: Kozak, KubaX, dev; +Cc: Piasecki, JacekX, Kozak, KubaX

Hi Kuba,

> -----Original Message-----
> From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Kuba Kozak
> Sent: Friday, March 3, 2017 12:08 AM
> To: dev@dpdk.org
> Cc: Piasecki, JacekX; Kozak, KubaX
> Subject: [dpdk-dev] [PATCH 2/4] net/e1000: add grouping of xstats for e1000
> driver
> 
> From: Jacek Piasecki <jacekx.piasecki@intel.com>
> 
> This patch extends the 'rte_igb_xstats_name_off' structure with additional field
> 'group_mask'. For each xstats there is now specified group (e.g. TX_GROUP),
> one xstatistic can be in several groups.
> To implement new functionality of retriving xstats by group on driver level, there
> are two functions added:
> eth_igb_xstats_get_by_group() and eth_igb_xstats_get_names_by_group()
> 
> Signed-off-by: Jacek Piasecki <jacekx.piasecki@intel.com>
> Signed-off-by: Kuba Kozak <kubax.kozak@intel.com
> 
>  #define IGBVF_NB_XSTATS (sizeof(rte_igbvf_stats_strings) / \ @@ -1771,6
> +1832,13 @@ struct rte_igb_xstats_name_off {
>  	stats->cexterr += E1000_READ_REG(hw, E1000_CEXTERR);
>  	stats->tsctc += E1000_READ_REG(hw, E1000_TSCTC);
>  	stats->tsctfc += E1000_READ_REG(hw, E1000_TSCTFC);
> +
> +	if (hw->mac.type == e1000_i350 || hw->mac.type == e1000_i210) {
> +		stats->o2bgptc += E1000_READ_REG(hw, E1000_O2BGPTC);
> +		stats->o2bspc += E1000_READ_REG(hw, E1000_O2BSPC);
> +		stats->b2ospc += E1000_READ_REG(hw, E1000_B2OSPC);
> +		stats->b2ogprc += E1000_READ_REG(hw, E1000_B2OGPRC);
> +	}
Seems this code doesn't belong to this topic. Could it be split to an isolate patch?

BTW, I can only find 3 patches in this patch set. 4/4 is missing.

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

* [PATCH 0/4] extend API to retriving xstats by group and xstats by name
@ 2017-03-03 12:54 Kuba Kozak
  0 siblings, 0 replies; 6+ messages in thread
From: Kuba Kozak @ 2017-03-03 12:54 UTC (permalink / raw)
  To: dev; +Cc: Kuba Kozak

Added three new functions to API: rte_eth_xstats_get_by_name(),
rte_eth_xstats_get_by_group(), rte_eth_xstats_get_names_by_group().

Extension of the 'rte_igb_xstats_name_off' structure
with additional field 'group_mask'. For each xstats there is now
specified group (e.g. TX_GROUP), one xstatistic can be in several groups.
To implement new functionality of retriving xstats by group
on e1000 driver level, there are two functions added:
eth_igb_xstats_get_by_group() and eth_igb_xstats_get_names_by_group(),
on ixgbe driver level, there are new functions added:
ixgbe_dev_xstats_get_by_group() and ixgbe_dev_xstats_get_names_by_group()

Extended functionality of proc_info application:
--xstats-name NAME: to display single xstat value by NAME
--xstats-group GROUPNAME: to display group of xstats by GROUPNAME

Jacek Piasecki (4):
  ethdev: add retrieving xstats by group and xstats by name
  net/e1000: add grouping of xstats for e1000 driver
  net/ixgbe: add grouping of xstats for ixgbe driver
  app/proc_info: add support for xstats-name and xstats-group

 app/proc_info/main.c             | 112 ++++++++-
 drivers/net/e1000/igb_ethdev.c   | 261 +++++++++++++++-----
 drivers/net/ixgbe/ixgbe_ethdev.c | 496 +++++++++++++++++++++++++++++++--------
 lib/librte_ether/rte_ethdev.c    | 310 +++++++++++++++++++++++-
 lib/librte_ether/rte_ethdev.h    | 105 ++++++++-
 5 files changed, 1114 insertions(+), 170 deletions(-)

-- 
1.9.1

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

end of thread, other threads:[~2017-03-03 10:56 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-03-02 16:07 [PATCH 0/4] extend API to retriving xstats by group and xstats by name Kuba Kozak
2017-03-02 16:07 ` [PATCH 1/4] ethdev: add retrieving " Kuba Kozak
2017-03-02 16:07 ` [PATCH 2/4] net/e1000: add grouping of xstats for e1000 driver Kuba Kozak
2017-03-03  1:35   ` Lu, Wenzhuo
2017-03-02 16:07 ` [PATCH 3/4] net/ixgbe: add grouping of xstats for ixgbe driver Kuba Kozak
2017-03-03 12:54 [PATCH 0/4] extend API to retriving xstats by group and xstats by name Kuba Kozak

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.