Discussion:
[dpdk-dev] [PATCH v2 00/11] Port XStats
(too old to reply)
Harry van Haaren
2015-09-30 09:40:11 UTC
Permalink
This patchset adds an implementation of the xstats_get() and xstats_reset() API to the following PMDs: virtio, igb, igbvf, ixgbe, ixgbevf, i40e, i40evf and fm10k.

The xstats API allows DPDK apps to gain access to extended statistics from each port on a NIC. These statistics are structured as per a scheme detailed in the patch for the doc/prog_guide.

v2: Send correct patchset.

Harry van Haaren (11):
doc: add extended statistics notes
doc: add extended statistics to prog_guide
ethdev: update xstats_get() strings and Q handling
virtio: add xstats() implementation
igb: add xstats() implementation
igbvf: add xstats() implementation
ixgbe: update statistic strings to scheme
ixgbevf: add xstats() functions to VF
i40e: add xstats() implementation
i40evf: add xstats() implementation
fm10k: add xstats() implementation

doc/guides/prog_guide/poll_mode_drv.rst | 51 ++++-
doc/guides/rel_notes/release_2_2.rst | 12 ++
drivers/net/e1000/igb_ethdev.c | 195 +++++++++++++++++-
drivers/net/fm10k/fm10k_ethdev.c | 69 +++++++
drivers/net/i40e/i40e_ethdev.c | 268 ++++++++++++++++++++++++-
drivers/net/i40e/i40e_ethdev_vf.c | 89 +++++++-
drivers/net/ixgbe/ixgbe_ethdev.c | 346 +++++++++++++++++++++++++++++---
drivers/net/virtio/virtio_ethdev.c | 82 +++++++-
lib/librte_ether/rte_ethdev.c | 15 +-
9 files changed, 1075 insertions(+), 52 deletions(-)
--
1.9.1
Harry van Haaren
2015-09-30 09:40:12 UTC
Permalink
Add release notes for this patchset.

Signed-off-by: Harry van Haaren <***@intel.com>
---
doc/guides/rel_notes/release_2_2.rst | 12 ++++++++++++
1 file changed, 12 insertions(+)

diff --git a/doc/guides/rel_notes/release_2_2.rst b/doc/guides/rel_notes/release_2_2.rst
index 9a70dae..35f26d5 100644
--- a/doc/guides/rel_notes/release_2_2.rst
+++ b/doc/guides/rel_notes/release_2_2.rst
@@ -4,6 +4,18 @@ DPDK Release 2.2
New Features
------------

+* **Extended Statistics**
+
+ Define extended statistics naming scheme to store metadata in the name
+ string name of each statistic. Implemented the extended stats API for
+ these PMDs:
+
+ * igb
+ * igbvf
+ * i40e
+ * i40evf
+ * fm10k
+ * virtio

Resolved Issues
---------------
--
1.9.1
Harry van Haaren
2015-10-22 15:48:23 UTC
Permalink
This patchset adds an implementation of the xstats_get() and xstats_reset() API
to the following PMDs: virtio, igb, igbvf, ixgbe, ixgbevf, i40e, i40evf and
fm10k.

The xstats API allows DPDK apps to gain access to extended statistics from each
port on a NIC. These statistics are structured as per a scheme detailed in the
patch for the doc/prog_guide.


Harry van Haaren (11):
doc: add extended statistics notes
doc: add extended statistics to prog_guide
ethdev: update xstats_get() strings and Q handling
virtio: add xstats() implementation
igb: add xstats() implementation
igbvf: add xstats() implementation
ixgbe: update statistic strings to scheme
ixgbevf: add xstats() functions to VF
i40e: add xstats() implementation
i40evf: add xstats() implementation
fm10k: add xstats() implementation

doc/guides/prog_guide/poll_mode_drv.rst | 51 ++++-
doc/guides/rel_notes/release_2_2.rst | 12 ++
drivers/net/e1000/igb_ethdev.c | 194 +++++++++++++++++-
drivers/net/fm10k/fm10k_ethdev.c | 87 ++++++++
drivers/net/i40e/i40e_ethdev.c | 265 +++++++++++++++++++++++-
drivers/net/i40e/i40e_ethdev_vf.c | 89 +++++++-
drivers/net/ixgbe/ixgbe_ethdev.c | 346 +++++++++++++++++++++++++++++---
drivers/net/virtio/virtio_ethdev.c | 98 ++++++++-
drivers/net/virtio/virtio_rxtx.c | 32 +++
drivers/net/virtio/virtqueue.h | 4 +
lib/librte_ether/rte_ethdev.c | 38 ++--
11 files changed, 1154 insertions(+), 62 deletions(-)
--
1.9.1
Harry van Haaren
2015-10-22 15:48:24 UTC
Permalink
Add release notes for this patchset.

Signed-off-by: Harry van Haaren <***@intel.com>
---
doc/guides/rel_notes/release_2_2.rst | 12 ++++++++++++
1 file changed, 12 insertions(+)

diff --git a/doc/guides/rel_notes/release_2_2.rst b/doc/guides/rel_notes/release_2_2.rst
index 4f75cff..fe93629 100644
--- a/doc/guides/rel_notes/release_2_2.rst
+++ b/doc/guides/rel_notes/release_2_2.rst
@@ -9,6 +9,18 @@ New Features
* Added support for Jumbo Frames.
* Optimize forwarding performance for Chelsio T5 40GbE cards.

+* **Extended Statistics**
+
+ Define extended statistics naming scheme to store metadata in the name
+ string name of each statistic. Implemented the extended stats API for
+ these PMDs:
+
+ * igb
+ * igbvf
+ * i40e
+ * i40evf
+ * fm10k
+ * virtio

Resolved Issues
---------------
--
1.9.1
Harry van Haaren
2015-10-30 11:36:28 UTC
Permalink
This patchset adds an implementation of the xstats_get() and xstats_reset() API
to the following PMDs: virtio, igb, igbvf, ixgbe, ixgbevf, i40e, i40evf and
fm10k.

The xstats API allows DPDK apps to gain access to extended statistics from each
port on a NIC. These statistics are structured as per a scheme detailed in the
patch for the doc/prog_guide.

v4: Consistency of names, refactored Q stat code
v3: Added more stats to PMDs
v2: Send correct patchset

Harry van Haaren (10):
doc: add extended statistics to prog_guide
ethdev: update xstats_get() strings and Q handling
virtio: add xstats() implementation
igb: add xstats() implementation
igbvf: add xstats() implementation
ixgbe: add extended statistic strings
ixgbevf: add xstats() implementation
i40e: add xstats() implementation
i40evf: add xstats() implementation
fm10k: add xstats() implementation

doc/guides/prog_guide/poll_mode_drv.rst | 51 ++++++-
doc/guides/rel_notes/release_2_2.rst | 14 ++
drivers/net/e1000/igb_ethdev.c | 193 ++++++++++++++++++++++--
drivers/net/fm10k/fm10k_ethdev.c | 87 +++++++++++
drivers/net/i40e/i40e_ethdev.c | 217 ++++++++++++++++++++++++++-
drivers/net/i40e/i40e_ethdev_vf.c | 89 ++++++++++-
drivers/net/ixgbe/ixgbe_ethdev.c | 254 +++++++++++++++++++++++++++-----
drivers/net/virtio/virtio_ethdev.c | 98 +++++++++++-
drivers/net/virtio/virtio_rxtx.c | 32 ++++
drivers/net/virtio/virtqueue.h | 4 +
lib/librte_ether/rte_ethdev.c | 38 +++--
11 files changed, 1006 insertions(+), 71 deletions(-)
--
1.9.1
Harry van Haaren
2015-10-30 11:36:29 UTC
Permalink
Add extended statistic section to the programmers
guide, poll mode driver section. This section describes
how the strings stats are formatted, and how the client
code can use this to gather information about the stat.

Signed-off-by: Harry van Haaren <***@intel.com>
---
doc/guides/prog_guide/poll_mode_drv.rst | 51 ++++++++++++++++++++++++++++++++-
doc/guides/rel_notes/release_2_2.rst | 14 +++++++++
2 files changed, 64 insertions(+), 1 deletion(-)

diff --git a/doc/guides/prog_guide/poll_mode_drv.rst b/doc/guides/prog_guide/poll_mode_drv.rst
index 8780ba3..44cc9ce 100644
--- a/doc/guides/prog_guide/poll_mode_drv.rst
+++ b/doc/guides/prog_guide/poll_mode_drv.rst
@@ -1,5 +1,5 @@
.. BSD LICENSE
- Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
All rights reserved.

Redistribution and use in source and binary forms, with or without
@@ -294,3 +294,52 @@ Ethernet Device API
~~~~~~~~~~~~~~~~~~~

The Ethernet device API exported by the Ethernet PMDs is described in the *DPDK API Reference*.
+
+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.
+
+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
+strings split by a single underscore ``_``. The scheme is as follows:
+
+* direction
+* detail 1
+* detail 2
+* detail n
+* unit
+
+Examples of common statistics xstats strings, formatted to comply to the scheme
+proposed above:
+
+* ``rx_bytes``
+* ``rx_crc_errors``
+* ``tx_multicast_packets``
+
+The scheme, although quite simple, allows flexibility in presenting and reading
+information from the statistic strings. The following example illustrates the
+naming scheme:``rx_packets``. In this example, the string is split into two
+components. The first component ``rx`` indicates that the statistic is
+associated with the receive side of the NIC. The second component ``packets``
+indicates that the unit of measure is packets.
+
+A more complicated example: ``tx_size_128_to_255_packets``. In this example,
+``tx`` indicates transmission, ``size`` is the first detail, ``128`` etc are
+more details, and ``packets`` indicates that this is a packet counter.
+
+Some additions in the metadata scheme are as follows:
+
+* If the first part does not match ``rx`` or ``tx``, the statistic does not
+ have an affinity with either recieve of transmit.
+
+* If the first letter of the second part is ``q`` and this ``q`` is followed
+ by a number, this statistic is part of a specific queue.
+
+An example where queue numbers are used is as follows: ``tx_q7_bytes`` which
+indicates this statistic applies to queue number 7, and represents the number
+of transmitted bytes on that queue.
diff --git a/doc/guides/rel_notes/release_2_2.rst b/doc/guides/rel_notes/release_2_2.rst
index 89e4d58..8e29ec3 100644
--- a/doc/guides/rel_notes/release_2_2.rst
+++ b/doc/guides/rel_notes/release_2_2.rst
@@ -31,6 +31,20 @@ New Features

* **Added vhost-user multiple queue support.**

+* **Extended Statistics**
+
+ Define extended statistics naming scheme to store metadata in the name
+ string name of each statistic, refer to the Extended Statistics section
+ of the programmers guide. Implemented the extended stats API for these
+ PMDs:
+
+ * igb
+ * igbvf
+ * i40e
+ * i40evf
+ * fm10k
+ * virtio
+
Resolved Issues
---------------
--
1.9.1
Harry van Haaren
2015-11-02 10:18:57 UTC
Permalink
This patchset adds an implementation of the xstats_get() and xstats_reset() API
to the following PMDs: virtio, igb, igbvf, ixgbe, ixgbevf, i40e, i40evf and
fm10k.

The xstats API allows DPDK apps to gain access to extended statistics from each
port on a NIC. These statistics are structured as per a scheme detailed in the
patch for the doc/prog_guide.

v5: Fix Checkpatch inconsistencies
v4: Consistency of names, refactored Q stat code
v3: Added more stats to PMDs
v2: Send correct patchset

Harry van Haaren (10):
doc: add extended statistics to prog_guide
ethdev: update xstats_get() strings and Q handling
virtio: add xstats() implementation
igb: add xstats() implementation
igbvf: add xstats() implementation
ixgbe: add extended statistic strings
ixgbevf: add xstats() implementation
i40e: add xstats() implementation
i40evf: add xstats() implementation
fm10k: add xstats() implementation

doc/guides/prog_guide/poll_mode_drv.rst | 51 ++++++-
doc/guides/rel_notes/release_2_2.rst | 14 ++
drivers/net/e1000/igb_ethdev.c | 193 ++++++++++++++++++++++--
drivers/net/fm10k/fm10k_ethdev.c | 87 +++++++++++
drivers/net/i40e/i40e_ethdev.c | 215 ++++++++++++++++++++++++++-
drivers/net/i40e/i40e_ethdev_vf.c | 89 ++++++++++-
drivers/net/ixgbe/ixgbe_ethdev.c | 252 ++++++++++++++++++++++++++++----
drivers/net/virtio/virtio_ethdev.c | 98 ++++++++++++-
drivers/net/virtio/virtio_rxtx.c | 32 ++++
drivers/net/virtio/virtqueue.h | 4 +
lib/librte_ether/rte_ethdev.c | 38 +++--
11 files changed, 1004 insertions(+), 69 deletions(-)
--
1.9.1
Harry van Haaren
2015-11-02 10:18:58 UTC
Permalink
Add extended statistic section to the programmers
guide, poll mode driver section. This section describes
how the strings stats are formatted, and how the client
code can use this to gather information about the stat.

Signed-off-by: Harry van Haaren <***@intel.com>
---
doc/guides/prog_guide/poll_mode_drv.rst | 51 ++++++++++++++++++++++++++++++++-
doc/guides/rel_notes/release_2_2.rst | 14 +++++++++
2 files changed, 64 insertions(+), 1 deletion(-)

diff --git a/doc/guides/prog_guide/poll_mode_drv.rst b/doc/guides/prog_guide/poll_mode_drv.rst
index 8780ba3..44cc9ce 100644
--- a/doc/guides/prog_guide/poll_mode_drv.rst
+++ b/doc/guides/prog_guide/poll_mode_drv.rst
@@ -1,5 +1,5 @@
.. BSD LICENSE
- Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
All rights reserved.

Redistribution and use in source and binary forms, with or without
@@ -294,3 +294,52 @@ Ethernet Device API
~~~~~~~~~~~~~~~~~~~

The Ethernet device API exported by the Ethernet PMDs is described in the *DPDK API Reference*.
+
+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.
+
+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
+strings split by a single underscore ``_``. The scheme is as follows:
+
+* direction
+* detail 1
+* detail 2
+* detail n
+* unit
+
+Examples of common statistics xstats strings, formatted to comply to the scheme
+proposed above:
+
+* ``rx_bytes``
+* ``rx_crc_errors``
+* ``tx_multicast_packets``
+
+The scheme, although quite simple, allows flexibility in presenting and reading
+information from the statistic strings. The following example illustrates the
+naming scheme:``rx_packets``. In this example, the string is split into two
+components. The first component ``rx`` indicates that the statistic is
+associated with the receive side of the NIC. The second component ``packets``
+indicates that the unit of measure is packets.
+
+A more complicated example: ``tx_size_128_to_255_packets``. In this example,
+``tx`` indicates transmission, ``size`` is the first detail, ``128`` etc are
+more details, and ``packets`` indicates that this is a packet counter.
+
+Some additions in the metadata scheme are as follows:
+
+* If the first part does not match ``rx`` or ``tx``, the statistic does not
+ have an affinity with either recieve of transmit.
+
+* If the first letter of the second part is ``q`` and this ``q`` is followed
+ by a number, this statistic is part of a specific queue.
+
+An example where queue numbers are used is as follows: ``tx_q7_bytes`` which
+indicates this statistic applies to queue number 7, and represents the number
+of transmitted bytes on that queue.
diff --git a/doc/guides/rel_notes/release_2_2.rst b/doc/guides/rel_notes/release_2_2.rst
index 89e4d58..8e29ec3 100644
--- a/doc/guides/rel_notes/release_2_2.rst
+++ b/doc/guides/rel_notes/release_2_2.rst
@@ -31,6 +31,20 @@ New Features

* **Added vhost-user multiple queue support.**

+* **Extended Statistics**
+
+ Define extended statistics naming scheme to store metadata in the name
+ string name of each statistic, refer to the Extended Statistics section
+ of the programmers guide. Implemented the extended stats API for these
+ PMDs:
+
+ * igb
+ * igbvf
+ * i40e
+ * i40evf
+ * fm10k
+ * virtio
+
Resolved Issues
---------------
--
1.9.1
Harry van Haaren
2015-11-02 10:18:59 UTC
Permalink
Update the strings used for presenting stats to adhere
to the scheme previously presented. Updated xstats_get()
function to handle Q information only if xstats() is not
implemented in the PMD, providing the PMD with the needed
flexibility to expose its extended Q stats.

Signed-off-by: Harry van Haaren <***@intel.com>
---
lib/librte_ether/rte_ethdev.c | 38 +++++++++++++++++++++++---------------
1 file changed, 23 insertions(+), 15 deletions(-)

diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index f593f6e..07f0c26 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -137,27 +137,30 @@ struct rte_eth_xstats_name_off {
};

static const struct rte_eth_xstats_name_off rte_stats_strings[] = {
- {"rx_packets", offsetof(struct rte_eth_stats, ipackets)},
- {"tx_packets", offsetof(struct rte_eth_stats, opackets)},
- {"rx_bytes", offsetof(struct rte_eth_stats, ibytes)},
- {"tx_bytes", offsetof(struct rte_eth_stats, obytes)},
- {"tx_errors", offsetof(struct rte_eth_stats, oerrors)},
+ {"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)},
- {"alloc_rx_buff_failed", offsetof(struct rte_eth_stats, rx_nombuf)},
+ {"tx_errors", offsetof(struct rte_eth_stats, oerrors)},
+ {"rx_mbuf_allocation_errors", offsetof(struct rte_eth_stats,
+ rx_nombuf)},
};
+
#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[] = {
- {"rx_packets", offsetof(struct rte_eth_stats, q_ipackets)},
- {"rx_bytes", offsetof(struct rte_eth_stats, q_ibytes)},
+ {"packets", offsetof(struct rte_eth_stats, q_ipackets)},
+ {"bytes", offsetof(struct rte_eth_stats, q_ibytes)},
+ {"errors", offsetof(struct rte_eth_stats, q_errors)},
};
+
#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[] = {
- {"tx_packets", offsetof(struct rte_eth_stats, q_opackets)},
- {"tx_bytes", offsetof(struct rte_eth_stats, q_obytes)},
- {"tx_errors", offsetof(struct rte_eth_stats, q_errors)},
+ {"packets", offsetof(struct rte_eth_stats, q_opackets)},
+ {"bytes", offsetof(struct rte_eth_stats, q_obytes)},
};
#define RTE_NB_TXQ_STATS (sizeof(rte_txq_stats_strings) / \
sizeof(rte_txq_stats_strings[0]))
@@ -1666,8 +1669,6 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,

/* Return generic statistics */
count = RTE_NB_STATS;
- count += dev->data->nb_rx_queues * RTE_NB_RXQ_STATS;
- count += dev->data->nb_tx_queues * RTE_NB_TXQ_STATS;

/* implemented by the driver */
if (dev->dev_ops->xstats_get != NULL) {
@@ -1679,6 +1680,9 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,

if (xcount < 0)
return xcount;
+ } else {
+ count += dev->data->nb_rx_queues * RTE_NB_RXQ_STATS;
+ count += dev->data->nb_tx_queues * RTE_NB_TXQ_STATS;
}

if (n < count + xcount)
@@ -1698,6 +1702,10 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
xstats[count++].value = val;
}

+ /* if xstats_get() is implemented by the PMD, the Q stats are done */
+ if (dev->dev_ops->xstats_get != NULL)
+ return count + xcount;
+
/* per-rxq stats */
for (q = 0; q < dev->data->nb_rx_queues; q++) {
for (i = 0; i < RTE_NB_RXQ_STATS; i++) {
@@ -1706,7 +1714,7 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
q * sizeof(uint64_t));
val = *stats_ptr;
snprintf(xstats[count].name, sizeof(xstats[count].name),
- "rx_queue_%u_%s", q,
+ "rx_q%u_%s", q,
rte_rxq_stats_strings[i].name);
xstats[count++].value = val;
}
@@ -1720,7 +1728,7 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
q * sizeof(uint64_t));
val = *stats_ptr;
snprintf(xstats[count].name, sizeof(xstats[count].name),
- "tx_queue_%u_%s", q,
+ "tx_q%u_%s", q,
rte_txq_stats_strings[i].name);
xstats[count++].value = val;
}
--
1.9.1
Harry van Haaren
2015-11-02 10:19:00 UTC
Permalink
Add xstats() functions and statistic strings to virtio PMD.

Signed-off-by: Harry van Haaren <***@intel.com>
---
drivers/net/virtio/virtio_ethdev.c | 98 +++++++++++++++++++++++++++++++++++++-
drivers/net/virtio/virtio_rxtx.c | 32 +++++++++++++
drivers/net/virtio/virtqueue.h | 4 ++
3 files changed, 132 insertions(+), 2 deletions(-)

diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c
index 12fcc23..fe5afb9 100644
--- a/drivers/net/virtio/virtio_ethdev.c
+++ b/drivers/net/virtio/virtio_ethdev.c
@@ -80,7 +80,10 @@ static int virtio_dev_link_update(struct rte_eth_dev *dev,
static void virtio_set_hwaddr(struct virtio_hw *hw);
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 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 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,
@@ -109,6 +112,31 @@ static const struct rte_pci_id pci_id_virtio_map[] = {
{ .vendor_id = 0, /* sentinel */ },
};

+struct rte_virtio_xstats_name_off {
+ char name[RTE_ETH_XSTATS_NAME_SIZE];
+ unsigned offset;
+};
+
+/* [rt]x_qX_ is prepended to the name string here */
+static const struct rte_virtio_xstats_name_off rte_virtio_q_stat_strings[] = {
+ {"good_packets", offsetof(struct virtqueue, packets)},
+ {"good_bytes", offsetof(struct virtqueue, bytes)},
+ {"errors", offsetof(struct virtqueue, errors)},
+ {"multicast_packets", offsetof(struct virtqueue, multicast)},
+ {"broadcast_packets", offsetof(struct virtqueue, broadcast)},
+ {"undersize_packets", offsetof(struct virtqueue, size_bins[0])},
+ {"size_64_packets", offsetof(struct virtqueue, size_bins[1])},
+ {"size_65_127_packets", offsetof(struct virtqueue, size_bins[2])},
+ {"size_128_255_packets", offsetof(struct virtqueue, size_bins[3])},
+ {"size_256_511_packets", offsetof(struct virtqueue, size_bins[4])},
+ {"size_512_1023_packets", offsetof(struct virtqueue, size_bins[5])},
+ {"size_1024_1517_packets", offsetof(struct virtqueue, size_bins[6])},
+ {"size_1518_max_packets", offsetof(struct virtqueue, size_bins[7])},
+};
+
+#define VIRTIO_NB_Q_XSTATS (sizeof(rte_virtio_q_stat_strings) / \
+ sizeof(rte_virtio_q_stat_strings[0]))
+
static int
virtio_send_command(struct virtqueue *vq, struct virtio_pmd_ctrl *ctrl,
int *dlen, int pkt_num)
@@ -568,7 +596,9 @@ 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,
.stats_reset = virtio_dev_stats_reset,
+ .xstats_reset = virtio_dev_stats_reset,
.link_update = virtio_dev_link_update,
.rx_queue_setup = virtio_dev_rx_queue_setup,
.rx_queue_release = virtio_dev_rx_queue_release,
@@ -623,7 +653,7 @@ virtio_dev_atomic_write_link_status(struct rte_eth_dev *dev,
}

static void
-virtio_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
+virtio_update_stats(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
{
unsigned i;

@@ -660,6 +690,64 @@ virtio_dev_stats_get(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(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
+ unsigned n)
+{
+ unsigned i;
+ unsigned count = 0;
+
+ unsigned nstats = dev->data->nb_tx_queues * VIRTIO_NB_Q_XSTATS +
+ dev->data->nb_rx_queues * VIRTIO_NB_Q_XSTATS;
+
+ if (n < nstats)
+ return nstats;
+
+ for (i = 0; i < dev->data->nb_rx_queues; i++) {
+ struct virtqueue *rxvq = dev->data->rx_queues[i];
+
+ if (rxvq == NULL)
+ continue;
+
+ 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].value = *(uint64_t *)(((char *)rxvq) +
+ rte_virtio_q_stat_strings[t].offset);
+ count++;
+ }
+ }
+
+ for (i = 0; i < dev->data->nb_tx_queues; i++) {
+ struct virtqueue *txvq = dev->data->tx_queues[i];
+
+ if (txvq == NULL)
+ continue;
+
+ 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].value = *(uint64_t *)(((char *)txvq) +
+ rte_virtio_q_stat_strings[t].offset);
+ count++;
+ }
+ }
+
+ return count;
+}
+
+static void
+virtio_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
+{
+ virtio_update_stats(dev, stats);
+}
+
static void
virtio_dev_stats_reset(struct rte_eth_dev *dev)
{
@@ -673,6 +761,9 @@ virtio_dev_stats_reset(struct rte_eth_dev *dev)
txvq->packets = 0;
txvq->bytes = 0;
txvq->errors = 0;
+ txvq->multicast = 0;
+ txvq->broadcast = 0;
+ memset(txvq->size_bins, 0, sizeof(txvq->size_bins[0]) * 8);
}

for (i = 0; i < dev->data->nb_rx_queues; i++) {
@@ -683,6 +774,9 @@ virtio_dev_stats_reset(struct rte_eth_dev *dev)
rxvq->packets = 0;
rxvq->bytes = 0;
rxvq->errors = 0;
+ rxvq->multicast = 0;
+ rxvq->broadcast = 0;
+ memset(rxvq->size_bins, 0, sizeof(rxvq->size_bins[0]) * 8);
}

dev->data->rx_mbuf_alloc_failed = 0;
diff --git a/drivers/net/virtio/virtio_rxtx.c b/drivers/net/virtio/virtio_rxtx.c
index d35c5f9..7590485 100644
--- a/drivers/net/virtio/virtio_rxtx.c
+++ b/drivers/net/virtio/virtio_rxtx.c
@@ -482,6 +482,34 @@ virtio_discard_rxbuf(struct virtqueue *vq, struct rte_mbuf *m)
}
}

+static void
+virtio_update_packet_stats(struct virtqueue *vq, struct rte_mbuf *mbuf)
+{
+ uint32_t s = mbuf->pkt_len;
+ struct ether_addr *ea;
+
+ if (s == 64) {
+ vq->size_bins[1]++;
+ } else if (s > 64 && s < 1024) {
+ uint32_t bin;
+
+ /* count zeros, and offset into correct bin */
+ bin = (sizeof(s) * 8) - __builtin_clz(s) - 5;
+ vq->size_bins[bin]++;
+ } else {
+ if (s < 64)
+ vq->size_bins[0]++;
+ else if (s < 1519)
+ vq->size_bins[6]++;
+ else if (s >= 1519)
+ vq->size_bins[7]++;
+ }
+
+ ea = rte_pktmbuf_mtod(mbuf, struct ether_addr *);
+ vq->multicast += is_multicast_ether_addr(ea);
+ vq->broadcast += is_broadcast_ether_addr(ea);
+}
+
#define VIRTIO_MBUF_BURST_SZ 64
#define DESC_PER_CACHELINE (RTE_CACHE_LINE_SIZE / sizeof(struct vring_desc))
uint16_t
@@ -543,7 +571,9 @@ virtio_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
VIRTIO_DUMP_PACKET(rxm, rxm->data_len);

rx_pkts[nb_rx++] = rxm;
+
rxvq->bytes += rx_pkts[nb_rx - 1]->pkt_len;
+ virtio_update_packet_stats(rxvq, rxm);
}

rxvq->packets += nb_rx;
@@ -706,6 +736,7 @@ virtio_recv_mergeable_pkts(void *rx_queue,
rx_pkts[nb_rx]->data_len);

rxvq->bytes += rx_pkts[nb_rx]->pkt_len;
+ virtio_update_packet_stats(rxvq, rx_pkts[nb_rx]);
nb_rx++;
}

@@ -806,6 +837,7 @@ virtio_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
}
nb_tx++;
txvq->bytes += txm->pkt_len;
+ virtio_update_packet_stats(txvq, txm);
} else {
PMD_TX_LOG(ERR, "No free tx descriptors to transmit");
break;
diff --git a/drivers/net/virtio/virtqueue.h b/drivers/net/virtio/virtqueue.h
index 7789411..9032e6d 100644
--- a/drivers/net/virtio/virtqueue.h
+++ b/drivers/net/virtio/virtqueue.h
@@ -194,6 +194,10 @@ struct virtqueue {
uint64_t packets;
uint64_t bytes;
uint64_t errors;
+ uint64_t multicast;
+ uint64_t broadcast;
+ /* Size bins in array as RFC 2819, undersized [0], 64 [1], etc */
+ uint64_t size_bins[8];

struct vq_desc_extra {
void *cookie;
--
1.9.1
Harry van Haaren
2015-11-02 10:19:01 UTC
Permalink
Add xstats_get() and xstats_reset() functions to igb
driver, and the neccessary strings to expose these
NIC statistics.

Signed-off-by: Harry van Haaren <***@intel.com>
---
drivers/net/e1000/igb_ethdev.c | 135 +++++++++++++++++++++++++++++++++++++++--
1 file changed, 130 insertions(+), 5 deletions(-)

diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index 3ab082e..a5461e5 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -96,7 +96,10 @@ static int eth_igb_link_update(struct rte_eth_dev *dev,
int wait_to_complete);
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 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,
struct rte_eth_dev_info *dev_info);
static void eth_igbvf_infos_get(struct rte_eth_dev *dev,
@@ -291,7 +294,9 @@ static const struct eth_dev_ops eth_igb_ops = {
.allmulticast_disable = eth_igb_allmulticast_disable,
.link_update = eth_igb_link_update,
.stats_get = eth_igb_stats_get,
+ .xstats_get = eth_igb_xstats_get,
.stats_reset = eth_igb_stats_reset,
+ .xstats_reset = eth_igb_xstats_reset,
.dev_infos_get = eth_igb_infos_get,
.mtu_set = eth_igb_mtu_set,
.vlan_filter_set = eth_igb_vlan_filter_set,
@@ -353,6 +358,76 @@ static const struct eth_dev_ops igbvf_eth_dev_ops = {
.get_reg = igbvf_get_regs,
};

+/* store statistics names and its offset in stats structure */
+struct rte_igb_xstats_name_off {
+ char name[RTE_ETH_XSTATS_NAME_SIZE];
+ unsigned offset;
+};
+
+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)},
+ {"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)},
+ {"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)},
+ {"rx_size_512_to_1023_packets", offsetof(struct e1000_hw_stats,
+ prc1023)},
+ {"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)},
+ {"tx_size_512_to_1023_packets", offsetof(struct e1000_hw_stats,
+ ptc1023)},
+ {"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)},
+};
+
+#define IGB_NB_XSTATS (sizeof(rte_igb_stats_strings) / \
+ sizeof(rte_igb_stats_strings[0]))
+
/**
* Atomically reads the link status information from global
* structure rte_eth_dev.
@@ -1256,11 +1331,8 @@ igb_hardware_init(struct e1000_hw *hw)

/* This function is based on igb_update_stats_counters() in igb/if_igb.c */
static void
-eth_igb_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats)
+igb_read_stats_registers(struct e1000_hw *hw, struct e1000_hw_stats *stats)
{
- struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
- struct e1000_hw_stats *stats =
- E1000_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
int pause_frames;

if(hw->phy.media_type == e1000_media_type_copper ||
@@ -1366,6 +1438,16 @@ eth_igb_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats)
stats->cexterr += E1000_READ_REG(hw, E1000_CEXTERR);
stats->tsctc += E1000_READ_REG(hw, E1000_TSCTC);
stats->tsctfc += E1000_READ_REG(hw, E1000_TSCTFC);
+}
+
+static void
+eth_igb_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats)
+{
+ struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ struct e1000_hw_stats *stats =
+ E1000_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+
+ igb_read_stats_registers(hw, stats);

if (rte_stats == NULL)
return;
@@ -1408,6 +1490,50 @@ eth_igb_stats_reset(struct rte_eth_dev *dev)
}

static void
+eth_igb_xstats_reset(struct rte_eth_dev *dev)
+{
+ struct e1000_hw_stats *stats =
+ E1000_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+
+ /* HW registers are cleared on read */
+ eth_igb_xstats_get(dev, NULL, IGB_NB_XSTATS);
+
+ /* Reset software totals */
+ memset(stats, 0, sizeof(*stats));
+}
+
+static int
+eth_igb_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *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;
+
+ if (n < IGB_NB_XSTATS)
+ return IGB_NB_XSTATS;
+
+ 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++) {
+ snprintf(xstats[i].name, sizeof(xstats[i].name),
+ "%s", rte_igb_stats_strings[i].name);
+ xstats[i].value = *(uint64_t *)(((char *)hw_stats) +
+ rte_igb_stats_strings[i].offset);
+ }
+
+ return IGB_NB_XSTATS;
+}
+
+static void
eth_igbvf_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats)
{
struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
@@ -1462,7 +1588,6 @@ eth_igbvf_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats)
rte_stats->ilbbytes = hw_stats->gorlbc;
rte_stats->olbpackets = hw_stats->gptlbc;
rte_stats->olbbytes = hw_stats->gotlbc;
-
}

static void
--
1.9.1
Harry van Haaren
2015-11-02 10:19:02 UTC
Permalink
Add xstats functionality to igbvf PMD, adding
necessary statistic strings.

Signed-off-by: Harry van Haaren <***@intel.com>
---
drivers/net/e1000/igb_ethdev.c | 62 +++++++++++++++++++++++++++++++++++++-----
1 file changed, 55 insertions(+), 7 deletions(-)

diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index a5461e5..e57d436 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -152,7 +152,10 @@ static int igbvf_dev_start(struct rte_eth_dev *dev);
static void igbvf_dev_stop(struct rte_eth_dev *dev);
static void igbvf_dev_close(struct rte_eth_dev *dev);
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 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 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);
@@ -345,7 +348,9 @@ static const struct eth_dev_ops igbvf_eth_dev_ops = {
.dev_close = igbvf_dev_close,
.link_update = eth_igb_link_update,
.stats_get = eth_igbvf_stats_get,
+ .xstats_get = eth_igbvf_xstats_get,
.stats_reset = eth_igbvf_stats_reset,
+ .xstats_reset = eth_igbvf_stats_reset,
.vlan_filter_set = igbvf_vlan_filter_set,
.dev_infos_get = eth_igbvf_infos_get,
.rx_queue_setup = eth_igb_rx_queue_setup,
@@ -428,6 +433,17 @@ static const struct rte_igb_xstats_name_off rte_igb_stats_strings[] = {
#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)},
+};
+
+#define IGBVF_NB_XSTATS (sizeof(rte_igbvf_stats_strings) / \
+ sizeof(rte_igbvf_stats_strings[0]))
+
/**
* Atomically reads the link status information from global
* structure rte_eth_dev.
@@ -1534,12 +1550,8 @@ eth_igb_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
}

static void
-eth_igbvf_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats)
+igbvf_read_stats_registers(struct e1000_hw *hw, struct e1000_vf_stats *hw_stats)
{
- struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
- struct e1000_vf_stats *hw_stats = (struct e1000_vf_stats*)
- E1000_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
-
/* Good Rx packets, include VF loopback */
UPDATE_VF_STAT(E1000_VFGPRC,
hw_stats->last_gprc, hw_stats->gprc);
@@ -1575,6 +1587,43 @@ eth_igbvf_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats)
/* Good Tx loopback octets */
UPDATE_VF_STAT(E1000_VFGOTLBC,
hw_stats->last_gotlbc, hw_stats->gotlbc);
+}
+
+static int
+eth_igbvf_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
+ unsigned n)
+{
+ struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ struct e1000_vf_stats *hw_stats = (struct e1000_vf_stats *)
+ E1000_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+ unsigned i;
+
+ if (n < IGBVF_NB_XSTATS)
+ return IGBVF_NB_XSTATS;
+
+ igbvf_read_stats_registers(hw, hw_stats);
+
+ if (!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].value = *(uint64_t *)(((char *)hw_stats) +
+ rte_igbvf_stats_strings[i].offset);
+ }
+
+ return IGBVF_NB_XSTATS;
+}
+
+static void
+eth_igbvf_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats)
+{
+ struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ struct e1000_vf_stats *hw_stats = (struct e1000_vf_stats *)
+ E1000_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+
+ igbvf_read_stats_registers(hw, hw_stats);

if (rte_stats == NULL)
return;
@@ -1602,7 +1651,6 @@ eth_igbvf_stats_reset(struct rte_eth_dev *dev)
/* reset HW current stats*/
memset(&hw_stats->gprc, 0, sizeof(*hw_stats) -
offsetof(struct e1000_vf_stats, gprc));
-
}

static void
--
1.9.1
Harry van Haaren
2015-11-02 10:19:03 UTC
Permalink
Added and updated statistic strings as used by xstats_get(),
exposed extended queue statistics.

Signed-off-by: Harry van Haaren <***@intel.com>
---
drivers/net/ixgbe/ixgbe_ethdev.c | 203 +++++++++++++++++++++++++++++++++------
1 file changed, 172 insertions(+), 31 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 4373661..c657955 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -510,33 +510,95 @@ struct rte_ixgbe_xstats_name_off {
};

static const struct rte_ixgbe_xstats_name_off rte_ixgbe_stats_strings[] = {
- {"rx_illegal_byte_err", offsetof(struct ixgbe_hw_stats, errbc)},
- {"rx_len_err", offsetof(struct ixgbe_hw_stats, rlec)},
- {"rx_undersize_count", offsetof(struct ixgbe_hw_stats, ruc)},
- {"rx_oversize_count", offsetof(struct ixgbe_hw_stats, roc)},
- {"rx_fragment_count", offsetof(struct ixgbe_hw_stats, rfc)},
- {"rx_jabber_count", offsetof(struct ixgbe_hw_stats, rjc)},
- {"l3_l4_xsum_error", offsetof(struct ixgbe_hw_stats, xec)},
- {"mac_local_fault", offsetof(struct ixgbe_hw_stats, mlfc)},
- {"mac_remote_fault", offsetof(struct ixgbe_hw_stats, mrfc)},
- {"mac_short_pkt_discard", offsetof(struct ixgbe_hw_stats, mspdc)},
- {"fccrc_error", offsetof(struct ixgbe_hw_stats, fccrc)},
- {"fcoe_drop", offsetof(struct ixgbe_hw_stats, fcoerpdc)},
- {"fc_last_error", offsetof(struct ixgbe_hw_stats, fclast)},
- {"rx_broadcast_packets", offsetof(struct ixgbe_hw_stats, bprc)},
- {"rx_phy_multicast_packets", offsetof(struct ixgbe_hw_stats, mprc)},
- {"mgmt_pkts_dropped", offsetof(struct ixgbe_hw_stats, mngpdc)},
{"rx_crc_errors", offsetof(struct ixgbe_hw_stats, crcerrs)},
- {"fdir_match", offsetof(struct ixgbe_hw_stats, fdirmatch)},
- {"fdir_miss", offsetof(struct ixgbe_hw_stats, fdirmiss)},
- {"tx_flow_control_xon", offsetof(struct ixgbe_hw_stats, lxontxc)},
- {"rx_flow_control_xon", offsetof(struct ixgbe_hw_stats, lxonrxc)},
- {"tx_flow_control_xoff", offsetof(struct ixgbe_hw_stats, lxofftxc)},
- {"rx_flow_control_xoff", offsetof(struct ixgbe_hw_stats, lxoffrxc)},
+ {"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_size_512_to_1023_packets", offsetof(struct ixgbe_hw_stats,
+ prc1023)},
+ {"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_managment_packets", offsetof(struct ixgbe_hw_stats, mngprc)},
+ {"rx_managment_dropped", offsetof(struct ixgbe_hw_stats, mngpdc)},
+ {"tx_managment_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)},
+ {"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)},
+
+ {"flow_director_added_filters", offsetof(struct ixgbe_hw_stats,
+ fdirustat_add)},
+ {"flow_director_removed_filters", offsetof(struct ixgbe_hw_stats,
+ fdirustat_remove)},
+ {"flow_director_filter_add_errors", offsetof(struct ixgbe_hw_stats,
+ fdirfstat_fadd)},
+ {"flow_director_filter_remove_errors", offsetof(struct ixgbe_hw_stats,
+ fdirfstat_fremove)},
+ {"flow_director_matched_filters", offsetof(struct ixgbe_hw_stats,
+ fdirmatch)},
+ {"flow_director_missed_filters", offsetof(struct ixgbe_hw_stats,
+ fdirmiss)},
+
+ {"rx_fcoe_crc_errors", offsetof(struct ixgbe_hw_stats, fccrc)},
+ {"rx_fcoe_dropped", offsetof(struct ixgbe_hw_stats, fcoerpdc)},
+ {"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)},
+ {"rx_fcoe_no_direct_data_placement", offsetof(struct ixgbe_hw_stats,
+ fcoe_noddp)},
+ {"rx_fcoe_no_direct_data_placement_ext_buff",
+ offsetof(struct ixgbe_hw_stats, fcoe_noddp_ext_buff)},
+
+ {"tx_flow_control_xon_packets", offsetof(struct ixgbe_hw_stats,
+ lxontxc)},
+ {"rx_flow_control_xon_packets", offsetof(struct ixgbe_hw_stats,
+ lxonrxc)},
+ {"tx_flow_control_xoff_packets", offsetof(struct ixgbe_hw_stats,
+ lxofftxc)},
+ {"rx_flow_control_xoff_packets", offsetof(struct ixgbe_hw_stats,
+ lxoffrxc)},
+ {"rx_total_missed_packets", offsetof(struct ixgbe_hw_stats, mpctotal)},
};

-#define IXGBE_NB_XSTATS (sizeof(rte_ixgbe_stats_strings) / \
- sizeof(rte_ixgbe_stats_strings[0]))
+#define IXGBE_NB_HW_STATS (sizeof(rte_ixgbe_stats_strings) / \
+ sizeof(rte_ixgbe_stats_strings[0]))
+
+/* Per-queue statistics */
+#define IXBGE_NB_8_PER_Q_STATS (8 * 7)
+#define IXBGE_NB_16_PER_Q_STATS (16 * 5)
+#define IXGBE_NB_Q_STATS (IXBGE_NB_8_PER_Q_STATS + IXBGE_NB_16_PER_Q_STATS)
+
+#define IXGBE_NB_XSTATS (IXGBE_NB_HW_STATS + IXGBE_NB_Q_STATS)

/**
* Atomically reads the link status information from global
@@ -2257,7 +2319,7 @@ ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
total_qprdc = 0;

ixgbe_read_stats_registers(hw, hw_stats, &total_missed_rx, &total_qbrc,
- &total_qprc, &total_qprdc);
+ &total_qprc, &total_qprdc);

/* If this is a reset xstats is NULL, and we have cleared the
* registers by reading them.
@@ -2265,12 +2327,91 @@ ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
if (!xstats)
return 0;

- /* Extended stats */
- for (i = 0; i < IXGBE_NB_XSTATS; i++) {
- snprintf(xstats[i].name, sizeof(xstats[i].name),
- "%s", rte_ixgbe_stats_strings[i].name);
- xstats[i].value = *(uint64_t *)(((char *)hw_stats) +
- rte_ixgbe_stats_strings[i].offset);
+ /* 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++;
+ }
+
+ /* Per-Q stats, with 8 queues available */
+ for (i = 0; i < 8; i++) {
+ snprintf(xstats[count].name, sizeof(xstats[count].name),
+ "rx_q%u_mbuf_allocation_errors", i);
+ xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
+ offsetof(struct ixgbe_hw_stats, rnbc[i]));
+ count++;
+
+ snprintf(xstats[count].name, sizeof(xstats[count].name),
+ "rx_q%u_missed_packets", i);
+ xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
+ offsetof(struct ixgbe_hw_stats, mpc[i]));
+ count++;
+
+ snprintf(xstats[count].name, sizeof(xstats[count].name),
+ "rx_q%u_xon_priority_packets", i);
+ xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
+ offsetof(struct ixgbe_hw_stats, pxonrxc[i]));
+ count++;
+
+ snprintf(xstats[count].name, sizeof(xstats[count].name),
+ "tx_q%u_xon_priority_packets", i);
+ xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
+ offsetof(struct ixgbe_hw_stats, pxontxc[i]));
+ count++;
+
+ snprintf(xstats[count].name, sizeof(xstats[count].name),
+ "rx_q%u_xoff_priority_packets", i);
+ xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
+ offsetof(struct ixgbe_hw_stats, pxoffrxc[i]));
+ count++;
+
+ snprintf(xstats[count].name, sizeof(xstats[count].name),
+ "tx_q%u_xoff_priority_packets", i);
+ xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
+ offsetof(struct ixgbe_hw_stats, pxofftxc[i]));
+ count++;
+
+ snprintf(xstats[count].name, sizeof(xstats[count].name),
+ "xx_q%u_xon_to_xoff_priority_packets", i);
+ xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
+ offsetof(struct ixgbe_hw_stats, pxon2offc[i]));
+ count++;
+ }
+
+ for (i = 0; i < 16; i++) {
+ snprintf(xstats[count].name, sizeof(xstats[count].name),
+ "rx_q%u_packets", i);
+ xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
+ offsetof(struct ixgbe_hw_stats, qprc[i]));
+ count++;
+
+ snprintf(xstats[count].name, sizeof(xstats[count].name),
+ "rx_q%u_bytes", i);
+ xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
+ offsetof(struct ixgbe_hw_stats, qbrc[i]));
+ count++;
+
+ snprintf(xstats[count].name, sizeof(xstats[count].name),
+ "tx_q%u_packets", i);
+ xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
+ offsetof(struct ixgbe_hw_stats, qptc[i]));
+ count++;
+
+ snprintf(xstats[count].name, sizeof(xstats[count].name),
+ "tx_q%u_bytes", i);
+ xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
+ offsetof(struct ixgbe_hw_stats, qbtc[i]));
+ count++;
+
+ snprintf(xstats[count].name, sizeof(xstats[count].name),
+ "rx_q%u_dropped", i);
+ xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
+ offsetof(struct ixgbe_hw_stats, qprdc[i]));
+ count++;
}

return count;
--
1.9.1
Thomas Monjalon
2015-11-02 22:31:08 UTC
Permalink
+ {"rx_managment_packets", offsetof(struct ixgbe_hw_stats, mngprc)},
+ {"rx_managment_dropped", offsetof(struct ixgbe_hw_stats, mngpdc)},
+ {"tx_managment_packets", offsetof(struct ixgbe_hw_stats, mngptc)},
Looks to be a typo. Management?
Harry van Haaren
2015-11-02 10:19:04 UTC
Permalink
Add xstats() functions and stat strings as necessary to ixgbevf PMD.

Signed-off-by: Harry van Haaren <***@intel.com>
---
drivers/net/ixgbe/ixgbe_ethdev.c | 49 +++++++++++++++++++++++++++++++++++++++-
1 file changed, 48 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index c657955..0a6288a 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -149,6 +149,8 @@ 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);
+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_queue_stats_mapping_set(struct rte_eth_dev *eth_dev,
@@ -477,7 +479,9 @@ static const struct eth_dev_ops ixgbevf_eth_dev_ops = {
.dev_stop = ixgbevf_dev_stop,
.link_update = ixgbe_dev_link_update,
.stats_get = ixgbevf_dev_stats_get,
+ .xstats_get = ixgbevf_dev_xstats_get,
.stats_reset = ixgbevf_dev_stats_reset,
+ .xstats_reset = ixgbevf_dev_stats_reset,
.dev_close = ixgbevf_dev_close,
.dev_infos_get = ixgbevf_dev_info_get,
.mtu_set = ixgbevf_dev_set_mtu,
@@ -600,6 +604,13 @@ static const struct rte_ixgbe_xstats_name_off rte_ixgbe_stats_strings[] = {

#define IXGBE_NB_XSTATS (IXGBE_NB_HW_STATS + IXGBE_NB_Q_STATS)

+static const struct rte_ixgbe_xstats_name_off rte_ixgbevf_stats_strings[] = {
+ {"rx_multicast_packets", offsetof(struct ixgbevf_hw_stats, vfmprc)},
+};
+
+#define IXGBEVF_NB_XSTATS (sizeof(rte_ixgbevf_stats_strings) / \
+ sizeof(rte_ixgbevf_stats_strings[0]))
+
/**
* Atomically reads the link status information from global
* structure rte_eth_dev.
@@ -2431,7 +2442,7 @@ ixgbe_dev_xstats_reset(struct rte_eth_dev *dev)
}

static void
-ixgbevf_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
+ixgbevf_update_stats(struct rte_eth_dev *dev)
{
struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
struct ixgbevf_hw_stats *hw_stats = (struct ixgbevf_hw_stats*)
@@ -2456,6 +2467,42 @@ ixgbevf_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
/* Rx Multicst Packet */
UPDATE_VF_STAT(IXGBE_VFMPRC,
hw_stats->last_vfmprc, hw_stats->vfmprc);
+}
+
+static int
+ixgbevf_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
+ unsigned n)
+{
+ struct ixgbevf_hw_stats *hw_stats = (struct ixgbevf_hw_stats *)
+ IXGBE_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+ unsigned i;
+
+ if (n < IXGBEVF_NB_XSTATS)
+ return IXGBEVF_NB_XSTATS;
+
+ ixgbevf_update_stats(dev);
+
+ if (!xstats)
+ return 0;
+
+ /* 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].value = *(uint64_t *)(((char *)hw_stats) +
+ rte_ixgbevf_stats_strings[i].offset);
+ }
+
+ return IXGBEVF_NB_XSTATS;
+}
+
+static void
+ixgbevf_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
+{
+ struct ixgbevf_hw_stats *hw_stats = (struct ixgbevf_hw_stats *)
+ IXGBE_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+
+ ixgbevf_update_stats(dev);

if (stats == NULL)
return;
--
1.9.1
Harry van Haaren
2015-11-02 10:19:05 UTC
Permalink
Add xstats functions to i40e PMD, allowing extended statistics
to be retrieved from the NIC and exposed to the DPDK.

Signed-off-by: Harry van Haaren <***@intel.com>
---
drivers/net/i40e/i40e_ethdev.c | 215 +++++++++++++++++++++++++++++++++++++++--
1 file changed, 209 insertions(+), 6 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 2dd9fdc..089d414 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -127,7 +127,10 @@ static int i40e_dev_set_link_up(struct rte_eth_dev *dev);
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);
static void i40e_dev_stats_reset(struct rte_eth_dev *dev);
+static void i40e_dev_xstats_reset(struct rte_eth_dev *dev);
static int i40e_dev_queue_stats_mapping_set(struct rte_eth_dev *dev,
uint16_t queue_id,
uint8_t stat_idx,
@@ -232,6 +235,8 @@ static int i40e_timesync_read_rx_timestamp(struct rte_eth_dev *dev,
uint32_t flags);
static int i40e_timesync_read_tx_timestamp(struct rte_eth_dev *dev,
struct timespec *timestamp);
+static void i40e_read_stats_registers(struct i40e_pf *pf, struct i40e_hw *hw);
+

static const struct rte_pci_id pci_id_i40e_map[] = {
#define RTE_PCI_DEV_ID_DECL_I40E(vend, dev) {RTE_PCI_DEVICE(vend, dev)},
@@ -252,7 +257,9 @@ static const struct eth_dev_ops i40e_eth_dev_ops = {
.dev_set_link_down = i40e_dev_set_link_down,
.link_update = i40e_dev_link_update,
.stats_get = i40e_dev_stats_get,
+ .xstats_get = i40e_dev_xstats_get,
.stats_reset = i40e_dev_stats_reset,
+ .xstats_reset = i40e_dev_xstats_reset,
.queue_stats_mapping_set = i40e_dev_queue_stats_mapping_set,
.dev_infos_get = i40e_dev_info_get,
.vlan_filter_set = i40e_vlan_filter_set,
@@ -291,6 +298,101 @@ static const struct eth_dev_ops i40e_eth_dev_ops = {
.timesync_read_tx_timestamp = i40e_timesync_read_tx_timestamp,
};

+/* store statistics names and its offset in stats structure */
+struct rte_i40e_xstats_name_off {
+ char name[RTE_ETH_XSTATS_NAME_SIZE];
+ unsigned offset;
+};
+
+static const struct rte_i40e_xstats_name_off rte_i40e_stats_strings[] = {
+ {"rx_unicast_packets", offsetof(struct i40e_eth_stats, rx_unicast)},
+ {"rx_multicast_packets", offsetof(struct i40e_eth_stats, rx_multicast)},
+ {"rx_broadcast_packets", offsetof(struct i40e_eth_stats, rx_broadcast)},
+ {"rx_dropped", offsetof(struct i40e_eth_stats, rx_discards)},
+ {"rx_unknown_protocol_packets", offsetof(struct i40e_eth_stats,
+ rx_unknown_protocol)},
+ {"tx_unicast_packets", offsetof(struct i40e_eth_stats, tx_unicast)},
+ {"tx_multicast_packets", offsetof(struct i40e_eth_stats, tx_multicast)},
+ {"tx_broadcast_packets", offsetof(struct i40e_eth_stats, tx_broadcast)},
+ {"tx_dropped", offsetof(struct i40e_eth_stats, tx_discards)},
+};
+
+static const struct rte_i40e_xstats_name_off rte_i40e_hw_port_strings[] = {
+ {"tx_link_down_dropped", offsetof(struct i40e_hw_port_stats,
+ tx_dropped_link_down)},
+ {"rx_crc_errors", offsetof(struct i40e_hw_port_stats, crc_errors)},
+ {"rx_illegal_byte_errors", offsetof(struct i40e_hw_port_stats,
+ illegal_bytes)},
+ {"rx_error_bytes", offsetof(struct i40e_hw_port_stats, error_bytes)},
+ {"mac_local_errors", offsetof(struct i40e_hw_port_stats,
+ mac_local_faults)},
+ {"mac_remote_errors", offsetof(struct i40e_hw_port_stats,
+ mac_remote_faults)},
+ {"rx_length_errors", offsetof(struct i40e_hw_port_stats,
+ rx_length_errors)},
+ {"tx_xon_packets", offsetof(struct i40e_hw_port_stats, link_xon_tx)},
+ {"rx_xon_packets", offsetof(struct i40e_hw_port_stats, link_xon_rx)},
+ {"tx_xoff_packets", offsetof(struct i40e_hw_port_stats, link_xoff_tx)},
+ {"rx_xoff_packets", offsetof(struct i40e_hw_port_stats, link_xoff_rx)},
+ {"rx_size_64_packets", offsetof(struct i40e_hw_port_stats, rx_size_64)},
+ {"rx_size_65_to_127_packets", offsetof(struct i40e_hw_port_stats,
+ rx_size_127)},
+ {"rx_size_128_to_255_packets", offsetof(struct i40e_hw_port_stats,
+ rx_size_255)},
+ {"rx_size_256_to_511_packets", offsetof(struct i40e_hw_port_stats,
+ rx_size_511)},
+ {"rx_size_512_to_1023_packets", offsetof(struct i40e_hw_port_stats,
+ rx_size_1023)},
+ {"rx_size_1024_to_1522_packets", offsetof(struct i40e_hw_port_stats,
+ rx_size_1522)},
+ {"rx_size_1523_to_max_packets", offsetof(struct i40e_hw_port_stats,
+ rx_size_big)},
+ {"rx_undersized_errors", offsetof(struct i40e_hw_port_stats,
+ rx_undersize)},
+ {"rx_oversize_errors", offsetof(struct i40e_hw_port_stats,
+ rx_oversize)},
+ {"rx_mac_short_dropped", offsetof(struct i40e_hw_port_stats,
+ mac_short_packet_dropped)},
+ {"rx_fragmented_errors", offsetof(struct i40e_hw_port_stats,
+ rx_fragments)},
+ {"rx_jabber_errors", offsetof(struct i40e_hw_port_stats, rx_jabber)},
+ {"tx_size_64_packets", offsetof(struct i40e_hw_port_stats, tx_size_64)},
+ {"tx_size_65_to_127_packets", offsetof(struct i40e_hw_port_stats,
+ tx_size_127)},
+ {"tx_size_128_to_255_packets", offsetof(struct i40e_hw_port_stats,
+ tx_size_255)},
+ {"tx_size_256_to_511_packets", offsetof(struct i40e_hw_port_stats,
+ tx_size_511)},
+ {"tx_size_512_to_1023_packets", offsetof(struct i40e_hw_port_stats,
+ tx_size_1023)},
+ {"tx_size_1024_to_1522_packets", offsetof(struct i40e_hw_port_stats,
+ tx_size_1522)},
+ {"tx_size_1523_to_max_packets", offsetof(struct i40e_hw_port_stats,
+ tx_size_big)},
+ {"rx_flow_director_atr_match_packets",
+ offsetof(struct i40e_hw_port_stats, fd_atr_match)},
+ {"rx_flow_director_sb_match_packets",
+ offsetof(struct i40e_hw_port_stats, fd_sb_match)},
+ {"tx_low_power_idle_status", offsetof(struct i40e_hw_port_stats,
+ tx_lpi_status)},
+ {"rx_low_power_idle_status", offsetof(struct i40e_hw_port_stats,
+ rx_lpi_status)},
+ {"tx_low_power_idle_count", offsetof(struct i40e_hw_port_stats,
+ tx_lpi_count)},
+ {"rx_low_power_idle_count", offsetof(struct i40e_hw_port_stats,
+ rx_lpi_count)},
+};
+
+/* Q Stats: 5 stats are exposed for each queue, implemented in xstats_get() */
+#define I40E_NB_HW_PORT_Q_STATS (8 * 5)
+
+#define I40E_NB_ETH_XSTATS (sizeof(rte_i40e_stats_strings) / \
+ sizeof(rte_i40e_stats_strings[0]))
+#define I40E_NB_HW_PORT_XSTATS (sizeof(rte_i40e_hw_port_strings) / \
+ sizeof(rte_i40e_hw_port_strings[0]))
+#define I40E_NB_XSTATS (I40E_NB_ETH_XSTATS + I40E_NB_HW_PORT_XSTATS + \
+ I40E_NB_HW_PORT_Q_STATS)
+
static struct eth_driver rte_i40e_pmd = {
.pci_drv = {
.name = "rte_i40e_pmd",
@@ -1322,16 +1424,12 @@ i40e_update_vsi_stats(struct i40e_vsi *vsi)
vsi->vsi_id);
}

-/* Get all statistics of a port */
static void
-i40e_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
+i40e_read_stats_registers(struct i40e_pf *pf, struct i40e_hw *hw)
{
- uint32_t i;
- struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
- struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ unsigned int i;
struct i40e_hw_port_stats *ns = &pf->stats; /* new stats */
struct i40e_hw_port_stats *os = &pf->stats_offset; /* old stats */
-
/* Get statistics of struct i40e_eth_stats */
i40e_stat_update_48(hw, I40E_GLPRT_GORCH(hw->port),
I40E_GLPRT_GORCL(hw->port),
@@ -1510,6 +1608,19 @@ i40e_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)

if (pf->main_vsi)
i40e_update_vsi_stats(pf->main_vsi);
+}
+
+/* Get all statistics of a port */
+static void
+i40e_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
+{
+ struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ struct i40e_hw_port_stats *ns = &pf->stats; /* new stats */
+ unsigned i;
+
+ /* call read registers - updates values, now write them to struct */
+ i40e_read_stats_registers(pf, hw);

stats->ipackets = ns->eth.rx_unicast + ns->eth.rx_multicast +
ns->eth.rx_broadcast;
@@ -1599,6 +1710,98 @@ i40e_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
PMD_DRV_LOG(DEBUG, "***************** PF stats end ********************");
}

+static void
+i40e_dev_xstats_reset(struct rte_eth_dev *dev)
+{
+ struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ struct i40e_hw_port_stats *hw_stats = &pf->stats;
+
+ /* The hw registers are cleared on read */
+ pf->offset_loaded = false;
+ i40e_read_stats_registers(pf, hw);
+
+ /* reset software counters */
+ memset(hw_stats, 0, sizeof(*hw_stats));
+}
+
+static int
+i40e_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
+ unsigned n)
+{
+ struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ unsigned i, count = 0;
+ struct i40e_hw_port_stats *hw_stats = &pf->stats;
+
+ if (n < I40E_NB_XSTATS)
+ return I40E_NB_XSTATS;
+
+ i40e_read_stats_registers(pf, hw);
+
+ /* Reset */
+ if (xstats == NULL)
+ return 0;
+
+ /* 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].value = *(uint64_t *)(((char *)&hw_stats->eth) +
+ rte_i40e_stats_strings[i].offset);
+ count++;
+ }
+
+ /* 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].value = *(uint64_t *)(((char *)hw_stats) +
+ rte_i40e_hw_port_strings[i].offset);
+ count++;
+ }
+
+ /* Get per-queue stats from i40e_hw_port struct */
+ for (i = 0; i < 8; i++) {
+ snprintf(xstats[count].name, sizeof(xstats[count].name),
+ "rx_q%u_xon_priority_packets", i);
+ xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
+ offsetof(struct i40e_hw_port_stats,
+ priority_xon_rx[i]));
+ count++;
+
+ snprintf(xstats[count].name, sizeof(xstats[count].name),
+ "rx_q%u_xoff_priority_packets", i);
+ xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
+ offsetof(struct i40e_hw_port_stats,
+ priority_xoff_rx[i]));
+ count++;
+
+ snprintf(xstats[count].name, sizeof(xstats[count].name),
+ "tx_q%u_xon_priority_packets", i);
+ xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
+ offsetof(struct i40e_hw_port_stats,
+ priority_xon_tx[i]));
+ count++;
+
+ snprintf(xstats[count].name, sizeof(xstats[count].name),
+ "tx_q%u_xoff_priority_packets", i);
+ xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
+ offsetof(struct i40e_hw_port_stats,
+ priority_xoff_tx[i]));
+ count++;
+
+ snprintf(xstats[count].name, sizeof(xstats[count].name),
+ "xx_q%u_xon_to_xoff_priority_packets", i);
+ xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
+ offsetof(struct i40e_hw_port_stats,
+ priority_xon_2_xoff[i]));
+ count++;
+ }
+
+ return I40E_NB_XSTATS;
+}
+
/* Reset the statistics */
static void
i40e_dev_stats_reset(struct rte_eth_dev *dev)
--
1.9.1
Harry van Haaren
2015-11-02 10:19:06 UTC
Permalink
Add implementation of xstats() functions in i40evf PMD.

Signed-off-by: Harry van Haaren <***@intel.com>
---
drivers/net/i40e/i40e_ethdev_vf.c | 89 +++++++++++++++++++++++++++++++++++++--
1 file changed, 86 insertions(+), 3 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
index b694400..24153fb 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -112,6 +112,9 @@ static int i40evf_dev_link_update(struct rte_eth_dev *dev,
__rte_unused int wait_to_complete);
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 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);
static void i40evf_vlan_offload_set(struct rte_eth_dev *dev, int mask);
@@ -148,6 +151,30 @@ static int i40evf_dev_rss_hash_conf_get(struct rte_eth_dev *dev,
/* Default hash key buffer for RSS */
static uint32_t rss_key_default[I40E_VFQF_HKEY_MAX_INDEX + 1];

+struct rte_i40evf_xstats_name_off {
+ char name[RTE_ETH_XSTATS_NAME_SIZE];
+ unsigned offset;
+};
+
+static const struct rte_i40evf_xstats_name_off rte_i40evf_stats_strings[] = {
+ {"rx_bytes", offsetof(struct i40e_eth_stats, rx_bytes)},
+ {"rx_unicast_packets", offsetof(struct i40e_eth_stats, rx_unicast)},
+ {"rx_multicast_packets", offsetof(struct i40e_eth_stats, rx_multicast)},
+ {"rx_broadcast_packets", offsetof(struct i40e_eth_stats, rx_broadcast)},
+ {"rx_dropped_packets", offsetof(struct i40e_eth_stats, rx_discards)},
+ {"rx_unknown_protocol_packets", offsetof(struct i40e_eth_stats,
+ rx_unknown_protocol)},
+ {"tx_bytes", offsetof(struct i40e_eth_stats, tx_bytes)},
+ {"tx_unicast_packets", offsetof(struct i40e_eth_stats, tx_bytes)},
+ {"tx_multicast_packets", offsetof(struct i40e_eth_stats, tx_bytes)},
+ {"tx_broadcast_packets", offsetof(struct i40e_eth_stats, tx_bytes)},
+ {"tx_dropped_packets", offsetof(struct i40e_eth_stats, tx_bytes)},
+ {"tx_error_packets", offsetof(struct i40e_eth_stats, tx_bytes)},
+};
+
+#define I40EVF_NB_XSTATS (sizeof(rte_i40evf_stats_strings) / \
+ sizeof(rte_i40evf_stats_strings[0]))
+
static const struct eth_dev_ops i40evf_eth_dev_ops = {
.dev_configure = i40evf_dev_configure,
.dev_start = i40evf_dev_start,
@@ -158,6 +185,8 @@ static const struct eth_dev_ops i40evf_eth_dev_ops = {
.allmulticast_disable = i40evf_dev_allmulticast_disable,
.link_update = i40evf_dev_link_update,
.stats_get = i40evf_dev_stats_get,
+ .xstats_get = i40evf_dev_xstats_get,
+ .xstats_reset = i40evf_dev_xstats_reset,
.dev_close = i40evf_dev_close,
.dev_infos_get = i40evf_dev_info_get,
.vlan_filter_set = i40evf_vlan_filter_set,
@@ -888,11 +917,10 @@ i40evf_del_mac_addr(struct rte_eth_dev *dev, struct ether_addr *addr)
}

static int
-i40evf_get_statics(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
+i40evf_update_stats(struct rte_eth_dev *dev, struct i40e_eth_stats **pstats)
{
struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
struct i40e_virtchnl_queue_select q_stats;
- struct i40e_eth_stats *pstats;
int err;
struct vf_cmd_info args;

@@ -907,9 +935,23 @@ i40evf_get_statics(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
err = i40evf_execute_vf_cmd(dev, &args);
if (err) {
PMD_DRV_LOG(ERR, "fail to execute command OP_GET_STATS");
+ *pstats = NULL;
return err;
}
- pstats = (struct i40e_eth_stats *)args.out_buffer;
+ *pstats = (struct i40e_eth_stats *)args.out_buffer;
+ return 0;
+}
+
+static int
+i40evf_get_statics(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
+{
+ int ret;
+ struct i40e_eth_stats *pstats = NULL;
+
+ ret = i40evf_update_stats(dev, &pstats);
+ if (ret != 0)
+ return 0;
+
stats->ipackets = pstats->rx_unicast + pstats->rx_multicast +
pstats->rx_broadcast;
stats->opackets = pstats->tx_broadcast + pstats->tx_multicast +
@@ -922,6 +964,47 @@ i40evf_get_statics(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
return 0;
}

+static void
+i40evf_dev_xstats_reset(struct rte_eth_dev *dev)
+{
+ struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
+ struct i40e_eth_stats *pstats = NULL;
+
+ /* read stat values to clear hardware registers */
+ i40evf_update_stats(dev, &pstats);
+
+ /* set stats offset base on current values */
+ vf->vsi.eth_stats_offset = vf->vsi.eth_stats;
+}
+
+static int i40evf_dev_xstats_get(struct rte_eth_dev *dev,
+ struct rte_eth_xstats *xstats, unsigned n)
+{
+ int ret;
+ unsigned i;
+ struct i40e_eth_stats *pstats = NULL;
+
+ if (n < I40EVF_NB_XSTATS)
+ return I40EVF_NB_XSTATS;
+
+ ret = i40evf_update_stats(dev, &pstats);
+ if (ret != 0)
+ return 0;
+
+ if (!xstats)
+ return 0;
+
+ /* 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].value = *(uint64_t *)(((char *)pstats) +
+ rte_i40evf_stats_strings[i].offset);
+ }
+
+ return I40EVF_NB_XSTATS;
+}
+
static int
i40evf_add_vlan(struct rte_eth_dev *dev, uint16_t vlanid)
{
--
1.9.1
Harry van Haaren
2015-11-02 10:19:07 UTC
Permalink
Add xstats() functions and statistic strings.

Signed-off-by: Harry van Haaren <***@intel.com>
---
drivers/net/fm10k/fm10k_ethdev.c | 87 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 87 insertions(+)

diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c
index b104fc2..13ca098 100644
--- a/drivers/net/fm10k/fm10k_ethdev.c
+++ b/drivers/net/fm10k/fm10k_ethdev.c
@@ -68,6 +68,46 @@ fm10k_MACVLAN_remove_all(struct rte_eth_dev *dev);
static void fm10k_tx_queue_release(void *queue);
static void fm10k_rx_queue_release(void *queue);

+struct fm10k_xstats_name_off {
+ char name[RTE_ETH_XSTATS_NAME_SIZE];
+ unsigned offset;
+};
+
+struct fm10k_xstats_name_off fm10k_hw_stats_strings[] = {
+ {"completion_timeout_count", offsetof(struct fm10k_hw_stats, timeout)},
+ {"unsupported_requests_count", offsetof(struct fm10k_hw_stats, ur)},
+ {"completer_abort_count", offsetof(struct fm10k_hw_stats, ca)},
+ {"unsupported_message_count", offsetof(struct fm10k_hw_stats, um)},
+ {"checksum_error_count", offsetof(struct fm10k_hw_stats, xec)},
+ {"vlan_dropped", offsetof(struct fm10k_hw_stats, vlan_drop)},
+ {"loopback_dropped", offsetof(struct fm10k_hw_stats, loopback_drop)},
+ {"rx_mbuf_allocation_errors", offsetof(struct fm10k_hw_stats,
+ nodesc_drop)},
+};
+
+#define FM10K_NB_HW_XSTATS (sizeof(fm10k_hw_stats_strings) / \
+ sizeof(fm10k_hw_stats_strings[0]))
+
+struct fm10k_xstats_name_off fm10k_hw_stats_rx_q_strings[] = {
+ {"packets", offsetof(struct fm10k_hw_stats_q, rx_packets)},
+ {"bytes", offsetof(struct fm10k_hw_stats_q, rx_bytes)},
+ {"dropped", offsetof(struct fm10k_hw_stats_q, rx_drops)},
+};
+
+#define FM10K_NB_RX_Q_XSTATS (sizeof(fm10k_hw_stats_rx_q_strings) / \
+ sizeof(fm10k_hw_stats_rx_q_strings[0]))
+
+struct fm10k_xstats_name_off fm10k_hw_stats_tx_q_strings[] = {
+ {"packets", offsetof(struct fm10k_hw_stats_q, tx_packets)},
+ {"bytes", offsetof(struct fm10k_hw_stats_q, tx_bytes)},
+};
+
+#define FM10K_NB_TX_Q_XSTATS (sizeof(fm10k_hw_stats_tx_q_strings) / \
+ sizeof(fm10k_hw_stats_tx_q_strings[0]))
+
+#define FM10K_NB_XSTATS (FM10K_NB_HW_XSTATS + FM10K_MAX_QUEUES_PF * \
+ (FM10K_NB_RX_Q_XSTATS + FM10K_NB_TX_Q_XSTATS))
+
static void
fm10k_mbx_initlock(struct fm10k_hw *hw)
{
@@ -867,6 +907,51 @@ fm10k_link_update(struct rte_eth_dev *dev,
return 0;
}

+static int
+fm10k_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
+ unsigned n)
+{
+ struct fm10k_hw_stats *hw_stats =
+ FM10K_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+ unsigned i, q, count = 0;
+
+ if (n < FM10K_NB_XSTATS)
+ return FM10K_NB_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].value = *(uint64_t *)(((char *)hw_stats) +
+ fm10k_hw_stats_strings[count].offset);
+ 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[count].name, sizeof(xstats[count].name),
+ "rx_q%u_%s", q,
+ fm10k_hw_stats_rx_q_strings[i].name);
+ 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].value =
+ *(uint64_t *)(((char *)&hw_stats->q[q]) +
+ fm10k_hw_stats_tx_q_strings[i].offset);
+ count++;
+ }
+ }
+
+ return FM10K_NB_XSTATS;
+}
+
static void
fm10k_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
{
@@ -2035,7 +2120,9 @@ static const struct eth_dev_ops fm10k_eth_dev_ops = {
.allmulticast_enable = fm10k_dev_allmulticast_enable,
.allmulticast_disable = fm10k_dev_allmulticast_disable,
.stats_get = fm10k_stats_get,
+ .xstats_get = fm10k_xstats_get,
.stats_reset = fm10k_stats_reset,
+ .xstats_reset = fm10k_stats_reset,
.link_update = fm10k_link_update,
.dev_infos_get = fm10k_dev_infos_get,
.vlan_filter_set = fm10k_vlan_filter_set,
--
1.9.1
Van Haaren, Harry
2015-11-02 10:24:26 UTC
Permalink
Subject: [PATCH v5 00/10] Port XStats
Series-acked-by: Maryam Tahhan <***@intel.com>

Same code as previous v4, same Ack. Will include in commit message in future.
-Harry
Thomas Monjalon
2015-11-02 23:23:15 UTC
Permalink
Subject: [PATCH v5 00/10] Port XStats
Applied with some typo fixes, thanks

I'm still not sure about the queue stats handling but it can be fixed
later if more people disagree with your choice.

Harry van Haaren
2015-10-30 11:36:30 UTC
Permalink
Update the strings used for presenting stats to adhere
to the scheme previously presented. Updated xstats_get()
function to handle Q information only if xstats() is not
implemented in the PMD, providing the PMD with the needed
flexibility to expose its extended Q stats.

Signed-off-by: Harry van Haaren <***@intel.com>
---
lib/librte_ether/rte_ethdev.c | 38 +++++++++++++++++++++++---------------
1 file changed, 23 insertions(+), 15 deletions(-)

diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index f593f6e..07f0c26 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -137,27 +137,30 @@ struct rte_eth_xstats_name_off {
};

static const struct rte_eth_xstats_name_off rte_stats_strings[] = {
- {"rx_packets", offsetof(struct rte_eth_stats, ipackets)},
- {"tx_packets", offsetof(struct rte_eth_stats, opackets)},
- {"rx_bytes", offsetof(struct rte_eth_stats, ibytes)},
- {"tx_bytes", offsetof(struct rte_eth_stats, obytes)},
- {"tx_errors", offsetof(struct rte_eth_stats, oerrors)},
+ {"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)},
- {"alloc_rx_buff_failed", offsetof(struct rte_eth_stats, rx_nombuf)},
+ {"tx_errors", offsetof(struct rte_eth_stats, oerrors)},
+ {"rx_mbuf_allocation_errors", offsetof(struct rte_eth_stats,
+ rx_nombuf)},
};
+
#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[] = {
- {"rx_packets", offsetof(struct rte_eth_stats, q_ipackets)},
- {"rx_bytes", offsetof(struct rte_eth_stats, q_ibytes)},
+ {"packets", offsetof(struct rte_eth_stats, q_ipackets)},
+ {"bytes", offsetof(struct rte_eth_stats, q_ibytes)},
+ {"errors", offsetof(struct rte_eth_stats, q_errors)},
};
+
#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[] = {
- {"tx_packets", offsetof(struct rte_eth_stats, q_opackets)},
- {"tx_bytes", offsetof(struct rte_eth_stats, q_obytes)},
- {"tx_errors", offsetof(struct rte_eth_stats, q_errors)},
+ {"packets", offsetof(struct rte_eth_stats, q_opackets)},
+ {"bytes", offsetof(struct rte_eth_stats, q_obytes)},
};
#define RTE_NB_TXQ_STATS (sizeof(rte_txq_stats_strings) / \
sizeof(rte_txq_stats_strings[0]))
@@ -1666,8 +1669,6 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,

/* Return generic statistics */
count = RTE_NB_STATS;
- count += dev->data->nb_rx_queues * RTE_NB_RXQ_STATS;
- count += dev->data->nb_tx_queues * RTE_NB_TXQ_STATS;

/* implemented by the driver */
if (dev->dev_ops->xstats_get != NULL) {
@@ -1679,6 +1680,9 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,

if (xcount < 0)
return xcount;
+ } else {
+ count += dev->data->nb_rx_queues * RTE_NB_RXQ_STATS;
+ count += dev->data->nb_tx_queues * RTE_NB_TXQ_STATS;
}

if (n < count + xcount)
@@ -1698,6 +1702,10 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
xstats[count++].value = val;
}

+ /* if xstats_get() is implemented by the PMD, the Q stats are done */
+ if (dev->dev_ops->xstats_get != NULL)
+ return count + xcount;
+
/* per-rxq stats */
for (q = 0; q < dev->data->nb_rx_queues; q++) {
for (i = 0; i < RTE_NB_RXQ_STATS; i++) {
@@ -1706,7 +1714,7 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
q * sizeof(uint64_t));
val = *stats_ptr;
snprintf(xstats[count].name, sizeof(xstats[count].name),
- "rx_queue_%u_%s", q,
+ "rx_q%u_%s", q,
rte_rxq_stats_strings[i].name);
xstats[count++].value = val;
}
@@ -1720,7 +1728,7 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
q * sizeof(uint64_t));
val = *stats_ptr;
snprintf(xstats[count].name, sizeof(xstats[count].name),
- "tx_queue_%u_%s", q,
+ "tx_q%u_%s", q,
rte_txq_stats_strings[i].name);
xstats[count++].value = val;
}
--
1.9.1
Thomas Monjalon
2015-11-02 07:59:26 UTC
Permalink
+ /* if xstats_get() is implemented by the PMD, the Q stats are done */
+ if (dev->dev_ops->xstats_get != NULL)
+ return count + xcount;
+
/* per-rxq stats */
for (q = 0; q < dev->data->nb_rx_queues; q++) {
for (i = 0; i < RTE_NB_RXQ_STATS; i++) {
Please could you explain why the generic per-queue stats are not used when
xstats is implemented in the driver?
Van Haaren, Harry
2015-11-02 10:17:12 UTC
Permalink
Hi,
Sent: Monday, November 2, 2015 7:59 AM
+ /* if xstats_get() is implemented by the PMD, the Q stats are done */
+ if (dev->dev_ops->xstats_get != NULL)
+ return count + xcount;
+
/* per-rxq stats */
for (q = 0; q < dev->data->nb_rx_queues; q++) {
for (i = 0; i < RTE_NB_RXQ_STATS; i++) {
Please could you explain why the generic per-queue stats are not used when
xstats is implemented in the driver?
Each PMD exposes its own queue stats so it has the flexibility of presenting them exactly has the hardware counts, in a human-readable order.

If the generic xstats were used, testpmd> xstats output would split a single queue's xstats to two places in the list. As stats are used during debugging, readability and clarity of the stats is vital in my opinion.

-Harry
Thomas Monjalon
2015-11-02 16:23:09 UTC
Permalink
Post by Van Haaren, Harry
Sent: Monday, November 2, 2015 7:59 AM
+ /* if xstats_get() is implemented by the PMD, the Q stats are done */
+ if (dev->dev_ops->xstats_get != NULL)
+ return count + xcount;
+
/* per-rxq stats */
for (q = 0; q < dev->data->nb_rx_queues; q++) {
for (i = 0; i < RTE_NB_RXQ_STATS; i++) {
Please could you explain why the generic per-queue stats are not used when
xstats is implemented in the driver?
Each PMD exposes its own queue stats so it has the flexibility of presenting them exactly has the hardware counts, in a human-readable order.
If the generic xstats were used, testpmd> xstats output would split a single queue's xstats to two places in the list. As stats are used during debugging, readability and clarity of the stats is vital in my opinion.
Output control is the role of testpmd, not the driver.
I think you can reorder the stats in testpmd given that you have defined
a clear scheme naming (thanks).
Harry van Haaren
2015-10-30 11:36:31 UTC
Permalink
Add xstats() functions and statistic strings to virtio PMD.

Signed-off-by: Harry van Haaren <***@intel.com>
---
drivers/net/virtio/virtio_ethdev.c | 98 +++++++++++++++++++++++++++++++++++++-
drivers/net/virtio/virtio_rxtx.c | 32 +++++++++++++
drivers/net/virtio/virtqueue.h | 4 ++
3 files changed, 132 insertions(+), 2 deletions(-)

diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c
index 12fcc23..4cf7a79 100644
--- a/drivers/net/virtio/virtio_ethdev.c
+++ b/drivers/net/virtio/virtio_ethdev.c
@@ -80,7 +80,10 @@ static int virtio_dev_link_update(struct rte_eth_dev *dev,
static void virtio_set_hwaddr(struct virtio_hw *hw);
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 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 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,
@@ -109,6 +112,31 @@ static const struct rte_pci_id pci_id_virtio_map[] = {
{ .vendor_id = 0, /* sentinel */ },
};

+struct rte_virtio_xstats_name_off {
+ char name[RTE_ETH_XSTATS_NAME_SIZE];
+ unsigned offset;
+};
+
+/* [rt]x_qX_ is prepended to the name string here */
+static const struct rte_virtio_xstats_name_off rte_virtio_q_stat_strings[] = {
+ {"good_packets", offsetof(struct virtqueue, packets)},
+ {"good_bytes", offsetof(struct virtqueue, bytes)},
+ {"errors", offsetof(struct virtqueue, errors)},
+ {"multicast_packets", offsetof(struct virtqueue, multicast)},
+ {"broadcast_packets", offsetof(struct virtqueue, broadcast)},
+ {"undersize_packets", offsetof(struct virtqueue, size_bins[0])},
+ {"size_64_packets", offsetof(struct virtqueue, size_bins[1])},
+ {"size_65_127_packets", offsetof(struct virtqueue, size_bins[2])},
+ {"size_128_255_packets", offsetof(struct virtqueue, size_bins[3])},
+ {"size_256_511_packets", offsetof(struct virtqueue, size_bins[4])},
+ {"size_512_1023_packets", offsetof(struct virtqueue, size_bins[5])},
+ {"size_1024_1517_packets", offsetof(struct virtqueue, size_bins[6])},
+ {"size_1518_max_packets", offsetof(struct virtqueue, size_bins[7])},
+};
+
+#define VIRTIO_NB_Q_XSTATS (sizeof(rte_virtio_q_stat_strings) / \
+ sizeof(rte_virtio_q_stat_strings[0]))
+
static int
virtio_send_command(struct virtqueue *vq, struct virtio_pmd_ctrl *ctrl,
int *dlen, int pkt_num)
@@ -568,7 +596,9 @@ 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,
.stats_reset = virtio_dev_stats_reset,
+ .xstats_reset = virtio_dev_stats_reset,
.link_update = virtio_dev_link_update,
.rx_queue_setup = virtio_dev_rx_queue_setup,
.rx_queue_release = virtio_dev_rx_queue_release,
@@ -623,7 +653,7 @@ virtio_dev_atomic_write_link_status(struct rte_eth_dev *dev,
}

static void
-virtio_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
+virtio_update_stats(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
{
unsigned i;

@@ -660,6 +690,64 @@ virtio_dev_stats_get(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(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
+ unsigned n)
+{
+ unsigned i;
+ unsigned count = 0;
+
+ unsigned nstats = dev->data->nb_tx_queues * VIRTIO_NB_Q_XSTATS +
+ dev->data->nb_rx_queues * VIRTIO_NB_Q_XSTATS;
+
+ if(n < nstats)
+ return nstats;
+
+ for (i = 0; i < dev->data->nb_rx_queues; i++) {
+ struct virtqueue *rxvq = dev->data->rx_queues[i];
+
+ if(rxvq == NULL)
+ continue;
+
+ 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].value = *(uint64_t *)(((char *)rxvq) +
+ rte_virtio_q_stat_strings[t].offset);
+ count++;
+ }
+ }
+
+ for (i = 0; i < dev->data->nb_tx_queues; i++) {
+ struct virtqueue *txvq = dev->data->tx_queues[i];
+
+ if(txvq == NULL)
+ continue;
+
+ 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].value = *(uint64_t *)(((char *)txvq) +
+ rte_virtio_q_stat_strings[t].offset);
+ count++;
+ }
+ }
+
+ return count;
+}
+
+static void
+virtio_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
+{
+ virtio_update_stats(dev, stats);
+}
+
static void
virtio_dev_stats_reset(struct rte_eth_dev *dev)
{
@@ -673,6 +761,9 @@ virtio_dev_stats_reset(struct rte_eth_dev *dev)
txvq->packets = 0;
txvq->bytes = 0;
txvq->errors = 0;
+ txvq->multicast = 0;
+ txvq->broadcast = 0;
+ memset(txvq->size_bins, 0, sizeof(txvq->size_bins[0]) * 8);
}

for (i = 0; i < dev->data->nb_rx_queues; i++) {
@@ -683,6 +774,9 @@ virtio_dev_stats_reset(struct rte_eth_dev *dev)
rxvq->packets = 0;
rxvq->bytes = 0;
rxvq->errors = 0;
+ rxvq->multicast = 0;
+ rxvq->broadcast = 0;
+ memset(rxvq->size_bins, 0, sizeof(rxvq->size_bins[0]) * 8);
}

dev->data->rx_mbuf_alloc_failed = 0;
diff --git a/drivers/net/virtio/virtio_rxtx.c b/drivers/net/virtio/virtio_rxtx.c
index d35c5f9..a615916 100644
--- a/drivers/net/virtio/virtio_rxtx.c
+++ b/drivers/net/virtio/virtio_rxtx.c
@@ -482,6 +482,34 @@ virtio_discard_rxbuf(struct virtqueue *vq, struct rte_mbuf *m)
}
}

+static void
+virtio_update_packet_stats(struct virtqueue *vq, struct rte_mbuf *mbuf)
+{
+ uint32_t s = mbuf->pkt_len;
+ struct ether_addr *ea;
+
+ if(s == 64) {
+ vq->size_bins[1]++;
+ } else if(s > 64 && s < 1024) {
+ uint32_t bin;
+
+ /* count zeros, and offset into correct bin */
+ bin = (sizeof(s) * 8) - __builtin_clz(s) - 5;
+ vq->size_bins[bin]++;
+ } else {
+ if(s < 64)
+ vq->size_bins[0]++;
+ else if(s < 1519)
+ vq->size_bins[6]++;
+ else if(s >= 1519)
+ vq->size_bins[7]++;
+ }
+
+ ea = rte_pktmbuf_mtod(mbuf, struct ether_addr *);
+ vq->multicast += is_multicast_ether_addr(ea);
+ vq->broadcast += is_broadcast_ether_addr(ea);
+}
+
#define VIRTIO_MBUF_BURST_SZ 64
#define DESC_PER_CACHELINE (RTE_CACHE_LINE_SIZE / sizeof(struct vring_desc))
uint16_t
@@ -543,7 +571,9 @@ virtio_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
VIRTIO_DUMP_PACKET(rxm, rxm->data_len);

rx_pkts[nb_rx++] = rxm;
+
rxvq->bytes += rx_pkts[nb_rx - 1]->pkt_len;
+ virtio_update_packet_stats(rxvq, rxm);
}

rxvq->packets += nb_rx;
@@ -706,6 +736,7 @@ virtio_recv_mergeable_pkts(void *rx_queue,
rx_pkts[nb_rx]->data_len);

rxvq->bytes += rx_pkts[nb_rx]->pkt_len;
+ virtio_update_packet_stats(rxvq, rx_pkts[nb_rx]);
nb_rx++;
}

@@ -806,6 +837,7 @@ virtio_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
}
nb_tx++;
txvq->bytes += txm->pkt_len;
+ virtio_update_packet_stats(txvq, txm);
} else {
PMD_TX_LOG(ERR, "No free tx descriptors to transmit");
break;
diff --git a/drivers/net/virtio/virtqueue.h b/drivers/net/virtio/virtqueue.h
index 7789411..9032e6d 100644
--- a/drivers/net/virtio/virtqueue.h
+++ b/drivers/net/virtio/virtqueue.h
@@ -194,6 +194,10 @@ struct virtqueue {
uint64_t packets;
uint64_t bytes;
uint64_t errors;
+ uint64_t multicast;
+ uint64_t broadcast;
+ /* Size bins in array as RFC 2819, undersized [0], 64 [1], etc */
+ uint64_t size_bins[8];

struct vq_desc_extra {
void *cookie;
--
1.9.1
Harry van Haaren
2015-10-30 11:36:32 UTC
Permalink
Add xstats_get() and xstats_reset() functions to igb
driver, and the neccessary strings to expose these
NIC statistics.

Signed-off-by: Harry van Haaren <***@intel.com>
---
drivers/net/e1000/igb_ethdev.c | 135 +++++++++++++++++++++++++++++++++++++++--
1 file changed, 130 insertions(+), 5 deletions(-)

diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index 3ab082e..7f2162d 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -96,7 +96,10 @@ static int eth_igb_link_update(struct rte_eth_dev *dev,
int wait_to_complete);
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 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,
struct rte_eth_dev_info *dev_info);
static void eth_igbvf_infos_get(struct rte_eth_dev *dev,
@@ -291,7 +294,9 @@ static const struct eth_dev_ops eth_igb_ops = {
.allmulticast_disable = eth_igb_allmulticast_disable,
.link_update = eth_igb_link_update,
.stats_get = eth_igb_stats_get,
+ .xstats_get = eth_igb_xstats_get,
.stats_reset = eth_igb_stats_reset,
+ .xstats_reset = eth_igb_xstats_reset,
.dev_infos_get = eth_igb_infos_get,
.mtu_set = eth_igb_mtu_set,
.vlan_filter_set = eth_igb_vlan_filter_set,
@@ -353,6 +358,76 @@ static const struct eth_dev_ops igbvf_eth_dev_ops = {
.get_reg = igbvf_get_regs,
};

+/* store statistics names and its offset in stats structure */
+struct rte_igb_xstats_name_off {
+ char name[RTE_ETH_XSTATS_NAME_SIZE];
+ unsigned offset;
+};
+
+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)},
+ {"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)},
+ {"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)},
+ {"rx_size_512_to_1023_packets", offsetof(struct e1000_hw_stats,
+ prc1023)},
+ {"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)},
+ {"tx_size_512_to_1023_packets", offsetof(struct e1000_hw_stats,
+ ptc1023)},
+ {"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)},
+};
+
+#define IGB_NB_XSTATS (sizeof(rte_igb_stats_strings) / \
+ sizeof(rte_igb_stats_strings[0]))
+
/**
* Atomically reads the link status information from global
* structure rte_eth_dev.
@@ -1256,11 +1331,8 @@ igb_hardware_init(struct e1000_hw *hw)

/* This function is based on igb_update_stats_counters() in igb/if_igb.c */
static void
-eth_igb_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats)
+igb_read_stats_registers(struct e1000_hw *hw, struct e1000_hw_stats *stats)
{
- struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
- struct e1000_hw_stats *stats =
- E1000_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
int pause_frames;

if(hw->phy.media_type == e1000_media_type_copper ||
@@ -1366,6 +1438,16 @@ eth_igb_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats)
stats->cexterr += E1000_READ_REG(hw, E1000_CEXTERR);
stats->tsctc += E1000_READ_REG(hw, E1000_TSCTC);
stats->tsctfc += E1000_READ_REG(hw, E1000_TSCTFC);
+}
+
+static void
+eth_igb_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats)
+{
+ struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ struct e1000_hw_stats *stats =
+ E1000_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+
+ igb_read_stats_registers(hw, stats);

if (rte_stats == NULL)
return;
@@ -1408,6 +1490,50 @@ eth_igb_stats_reset(struct rte_eth_dev *dev)
}

static void
+eth_igb_xstats_reset(struct rte_eth_dev *dev)
+{
+ struct e1000_hw_stats *stats =
+ E1000_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+
+ /* HW registers are cleared on read */
+ eth_igb_xstats_get(dev, NULL, IGB_NB_XSTATS);
+
+ /* Reset software totals */
+ memset(stats, 0, sizeof(*stats));
+}
+
+static int
+eth_igb_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *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;
+
+ if(n < IGB_NB_XSTATS)
+ return IGB_NB_XSTATS;
+
+ 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++) {
+ snprintf(xstats[i].name, sizeof(xstats[i].name),
+ "%s", rte_igb_stats_strings[i].name);
+ xstats[i].value = *(uint64_t *)(((char *)hw_stats) +
+ rte_igb_stats_strings[i].offset);
+ }
+
+ return IGB_NB_XSTATS;
+}
+
+static void
eth_igbvf_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats)
{
struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
@@ -1462,7 +1588,6 @@ eth_igbvf_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats)
rte_stats->ilbbytes = hw_stats->gorlbc;
rte_stats->olbpackets = hw_stats->gptlbc;
rte_stats->olbbytes = hw_stats->gotlbc;
-
}

static void
--
1.9.1
Harry van Haaren
2015-10-30 11:36:33 UTC
Permalink
Add xstats functionality to igbvf PMD, adding
necessary statistic strings.

Signed-off-by: Harry van Haaren <***@intel.com>
---
drivers/net/e1000/igb_ethdev.c | 62 +++++++++++++++++++++++++++++++++++++-----
1 file changed, 55 insertions(+), 7 deletions(-)

diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index 7f2162d..29d8ece 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -152,7 +152,10 @@ static int igbvf_dev_start(struct rte_eth_dev *dev);
static void igbvf_dev_stop(struct rte_eth_dev *dev);
static void igbvf_dev_close(struct rte_eth_dev *dev);
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 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 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);
@@ -345,7 +348,9 @@ static const struct eth_dev_ops igbvf_eth_dev_ops = {
.dev_close = igbvf_dev_close,
.link_update = eth_igb_link_update,
.stats_get = eth_igbvf_stats_get,
+ .xstats_get = eth_igbvf_xstats_get,
.stats_reset = eth_igbvf_stats_reset,
+ .xstats_reset = eth_igbvf_stats_reset,
.vlan_filter_set = igbvf_vlan_filter_set,
.dev_infos_get = eth_igbvf_infos_get,
.rx_queue_setup = eth_igb_rx_queue_setup,
@@ -428,6 +433,17 @@ static const struct rte_igb_xstats_name_off rte_igb_stats_strings[] = {
#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)},
+};
+
+#define IGBVF_NB_XSTATS (sizeof(rte_igbvf_stats_strings) / \
+ sizeof(rte_igbvf_stats_strings[0]))
+
/**
* Atomically reads the link status information from global
* structure rte_eth_dev.
@@ -1534,12 +1550,8 @@ eth_igb_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
}

static void
-eth_igbvf_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats)
+igbvf_read_stats_registers(struct e1000_hw *hw, struct e1000_vf_stats *hw_stats)
{
- struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
- struct e1000_vf_stats *hw_stats = (struct e1000_vf_stats*)
- E1000_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
-
/* Good Rx packets, include VF loopback */
UPDATE_VF_STAT(E1000_VFGPRC,
hw_stats->last_gprc, hw_stats->gprc);
@@ -1575,6 +1587,43 @@ eth_igbvf_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats)
/* Good Tx loopback octets */
UPDATE_VF_STAT(E1000_VFGOTLBC,
hw_stats->last_gotlbc, hw_stats->gotlbc);
+}
+
+static int
+eth_igbvf_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
+ unsigned n)
+{
+ struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ struct e1000_vf_stats *hw_stats = (struct e1000_vf_stats *)
+ E1000_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+ unsigned i;
+
+ if(n < IGBVF_NB_XSTATS)
+ return IGBVF_NB_XSTATS;
+
+ igbvf_read_stats_registers(hw, hw_stats);
+
+ if(!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].value = *(uint64_t *)(((char *)hw_stats) +
+ rte_igbvf_stats_strings[i].offset);
+ }
+
+ return IGBVF_NB_XSTATS;
+}
+
+static void
+eth_igbvf_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats)
+{
+ struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ struct e1000_vf_stats *hw_stats = (struct e1000_vf_stats *)
+ E1000_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+
+ igbvf_read_stats_registers(hw, hw_stats);

if (rte_stats == NULL)
return;
@@ -1602,7 +1651,6 @@ eth_igbvf_stats_reset(struct rte_eth_dev *dev)
/* reset HW current stats*/
memset(&hw_stats->gprc, 0, sizeof(*hw_stats) -
offsetof(struct e1000_vf_stats, gprc));
-
}

static void
--
1.9.1
Harry van Haaren
2015-10-30 11:36:34 UTC
Permalink
Added and updated statistic strings as used by xstats_get(),
exposed extended queue statistics.

Signed-off-by: Harry van Haaren <***@intel.com>
---
drivers/net/ixgbe/ixgbe_ethdev.c | 203 +++++++++++++++++++++++++++++++++------
1 file changed, 172 insertions(+), 31 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 4373661..c657955 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -510,33 +510,95 @@ struct rte_ixgbe_xstats_name_off {
};

static const struct rte_ixgbe_xstats_name_off rte_ixgbe_stats_strings[] = {
- {"rx_illegal_byte_err", offsetof(struct ixgbe_hw_stats, errbc)},
- {"rx_len_err", offsetof(struct ixgbe_hw_stats, rlec)},
- {"rx_undersize_count", offsetof(struct ixgbe_hw_stats, ruc)},
- {"rx_oversize_count", offsetof(struct ixgbe_hw_stats, roc)},
- {"rx_fragment_count", offsetof(struct ixgbe_hw_stats, rfc)},
- {"rx_jabber_count", offsetof(struct ixgbe_hw_stats, rjc)},
- {"l3_l4_xsum_error", offsetof(struct ixgbe_hw_stats, xec)},
- {"mac_local_fault", offsetof(struct ixgbe_hw_stats, mlfc)},
- {"mac_remote_fault", offsetof(struct ixgbe_hw_stats, mrfc)},
- {"mac_short_pkt_discard", offsetof(struct ixgbe_hw_stats, mspdc)},
- {"fccrc_error", offsetof(struct ixgbe_hw_stats, fccrc)},
- {"fcoe_drop", offsetof(struct ixgbe_hw_stats, fcoerpdc)},
- {"fc_last_error", offsetof(struct ixgbe_hw_stats, fclast)},
- {"rx_broadcast_packets", offsetof(struct ixgbe_hw_stats, bprc)},
- {"rx_phy_multicast_packets", offsetof(struct ixgbe_hw_stats, mprc)},
- {"mgmt_pkts_dropped", offsetof(struct ixgbe_hw_stats, mngpdc)},
{"rx_crc_errors", offsetof(struct ixgbe_hw_stats, crcerrs)},
- {"fdir_match", offsetof(struct ixgbe_hw_stats, fdirmatch)},
- {"fdir_miss", offsetof(struct ixgbe_hw_stats, fdirmiss)},
- {"tx_flow_control_xon", offsetof(struct ixgbe_hw_stats, lxontxc)},
- {"rx_flow_control_xon", offsetof(struct ixgbe_hw_stats, lxonrxc)},
- {"tx_flow_control_xoff", offsetof(struct ixgbe_hw_stats, lxofftxc)},
- {"rx_flow_control_xoff", offsetof(struct ixgbe_hw_stats, lxoffrxc)},
+ {"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_size_512_to_1023_packets", offsetof(struct ixgbe_hw_stats,
+ prc1023)},
+ {"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_managment_packets", offsetof(struct ixgbe_hw_stats, mngprc)},
+ {"rx_managment_dropped", offsetof(struct ixgbe_hw_stats, mngpdc)},
+ {"tx_managment_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)},
+ {"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)},
+
+ {"flow_director_added_filters", offsetof(struct ixgbe_hw_stats,
+ fdirustat_add)},
+ {"flow_director_removed_filters", offsetof(struct ixgbe_hw_stats,
+ fdirustat_remove)},
+ {"flow_director_filter_add_errors", offsetof(struct ixgbe_hw_stats,
+ fdirfstat_fadd)},
+ {"flow_director_filter_remove_errors", offsetof(struct ixgbe_hw_stats,
+ fdirfstat_fremove)},
+ {"flow_director_matched_filters", offsetof(struct ixgbe_hw_stats,
+ fdirmatch)},
+ {"flow_director_missed_filters", offsetof(struct ixgbe_hw_stats,
+ fdirmiss)},
+
+ {"rx_fcoe_crc_errors", offsetof(struct ixgbe_hw_stats, fccrc)},
+ {"rx_fcoe_dropped", offsetof(struct ixgbe_hw_stats, fcoerpdc)},
+ {"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)},
+ {"rx_fcoe_no_direct_data_placement", offsetof(struct ixgbe_hw_stats,
+ fcoe_noddp)},
+ {"rx_fcoe_no_direct_data_placement_ext_buff",
+ offsetof(struct ixgbe_hw_stats, fcoe_noddp_ext_buff)},
+
+ {"tx_flow_control_xon_packets", offsetof(struct ixgbe_hw_stats,
+ lxontxc)},
+ {"rx_flow_control_xon_packets", offsetof(struct ixgbe_hw_stats,
+ lxonrxc)},
+ {"tx_flow_control_xoff_packets", offsetof(struct ixgbe_hw_stats,
+ lxofftxc)},
+ {"rx_flow_control_xoff_packets", offsetof(struct ixgbe_hw_stats,
+ lxoffrxc)},
+ {"rx_total_missed_packets", offsetof(struct ixgbe_hw_stats, mpctotal)},
};

-#define IXGBE_NB_XSTATS (sizeof(rte_ixgbe_stats_strings) / \
- sizeof(rte_ixgbe_stats_strings[0]))
+#define IXGBE_NB_HW_STATS (sizeof(rte_ixgbe_stats_strings) / \
+ sizeof(rte_ixgbe_stats_strings[0]))
+
+/* Per-queue statistics */
+#define IXBGE_NB_8_PER_Q_STATS (8 * 7)
+#define IXBGE_NB_16_PER_Q_STATS (16 * 5)
+#define IXGBE_NB_Q_STATS (IXBGE_NB_8_PER_Q_STATS + IXBGE_NB_16_PER_Q_STATS)
+
+#define IXGBE_NB_XSTATS (IXGBE_NB_HW_STATS + IXGBE_NB_Q_STATS)

/**
* Atomically reads the link status information from global
@@ -2257,7 +2319,7 @@ ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
total_qprdc = 0;

ixgbe_read_stats_registers(hw, hw_stats, &total_missed_rx, &total_qbrc,
- &total_qprc, &total_qprdc);
+ &total_qprc, &total_qprdc);

/* If this is a reset xstats is NULL, and we have cleared the
* registers by reading them.
@@ -2265,12 +2327,91 @@ ixgbe_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
if (!xstats)
return 0;

- /* Extended stats */
- for (i = 0; i < IXGBE_NB_XSTATS; i++) {
- snprintf(xstats[i].name, sizeof(xstats[i].name),
- "%s", rte_ixgbe_stats_strings[i].name);
- xstats[i].value = *(uint64_t *)(((char *)hw_stats) +
- rte_ixgbe_stats_strings[i].offset);
+ /* 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++;
+ }
+
+ /* Per-Q stats, with 8 queues available */
+ for (i = 0; i < 8; i++) {
+ snprintf(xstats[count].name, sizeof(xstats[count].name),
+ "rx_q%u_mbuf_allocation_errors", i);
+ xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
+ offsetof(struct ixgbe_hw_stats, rnbc[i]));
+ count++;
+
+ snprintf(xstats[count].name, sizeof(xstats[count].name),
+ "rx_q%u_missed_packets", i);
+ xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
+ offsetof(struct ixgbe_hw_stats, mpc[i]));
+ count++;
+
+ snprintf(xstats[count].name, sizeof(xstats[count].name),
+ "rx_q%u_xon_priority_packets", i);
+ xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
+ offsetof(struct ixgbe_hw_stats, pxonrxc[i]));
+ count++;
+
+ snprintf(xstats[count].name, sizeof(xstats[count].name),
+ "tx_q%u_xon_priority_packets", i);
+ xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
+ offsetof(struct ixgbe_hw_stats, pxontxc[i]));
+ count++;
+
+ snprintf(xstats[count].name, sizeof(xstats[count].name),
+ "rx_q%u_xoff_priority_packets", i);
+ xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
+ offsetof(struct ixgbe_hw_stats, pxoffrxc[i]));
+ count++;
+
+ snprintf(xstats[count].name, sizeof(xstats[count].name),
+ "tx_q%u_xoff_priority_packets", i);
+ xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
+ offsetof(struct ixgbe_hw_stats, pxofftxc[i]));
+ count++;
+
+ snprintf(xstats[count].name, sizeof(xstats[count].name),
+ "xx_q%u_xon_to_xoff_priority_packets", i);
+ xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
+ offsetof(struct ixgbe_hw_stats, pxon2offc[i]));
+ count++;
+ }
+
+ for (i = 0; i < 16; i++) {
+ snprintf(xstats[count].name, sizeof(xstats[count].name),
+ "rx_q%u_packets", i);
+ xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
+ offsetof(struct ixgbe_hw_stats, qprc[i]));
+ count++;
+
+ snprintf(xstats[count].name, sizeof(xstats[count].name),
+ "rx_q%u_bytes", i);
+ xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
+ offsetof(struct ixgbe_hw_stats, qbrc[i]));
+ count++;
+
+ snprintf(xstats[count].name, sizeof(xstats[count].name),
+ "tx_q%u_packets", i);
+ xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
+ offsetof(struct ixgbe_hw_stats, qptc[i]));
+ count++;
+
+ snprintf(xstats[count].name, sizeof(xstats[count].name),
+ "tx_q%u_bytes", i);
+ xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
+ offsetof(struct ixgbe_hw_stats, qbtc[i]));
+ count++;
+
+ snprintf(xstats[count].name, sizeof(xstats[count].name),
+ "rx_q%u_dropped", i);
+ xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
+ offsetof(struct ixgbe_hw_stats, qprdc[i]));
+ count++;
}

return count;
--
1.9.1
Harry van Haaren
2015-10-30 11:36:35 UTC
Permalink
Add xstats() functions and stat strings as necessary to ixgbevf PMD.

Signed-off-by: Harry van Haaren <***@intel.com>
---
drivers/net/ixgbe/ixgbe_ethdev.c | 51 ++++++++++++++++++++++++++++++++++++++--
1 file changed, 49 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index c657955..53a646f 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -149,6 +149,8 @@ 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);
+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_queue_stats_mapping_set(struct rte_eth_dev *eth_dev,
@@ -477,7 +479,9 @@ static const struct eth_dev_ops ixgbevf_eth_dev_ops = {
.dev_stop = ixgbevf_dev_stop,
.link_update = ixgbe_dev_link_update,
.stats_get = ixgbevf_dev_stats_get,
+ .xstats_get = ixgbevf_dev_xstats_get,
.stats_reset = ixgbevf_dev_stats_reset,
+ .xstats_reset = ixgbevf_dev_stats_reset,
.dev_close = ixgbevf_dev_close,
.dev_infos_get = ixgbevf_dev_info_get,
.mtu_set = ixgbevf_dev_set_mtu,
@@ -600,6 +604,13 @@ static const struct rte_ixgbe_xstats_name_off rte_ixgbe_stats_strings[] = {

#define IXGBE_NB_XSTATS (IXGBE_NB_HW_STATS + IXGBE_NB_Q_STATS)

+static const struct rte_ixgbe_xstats_name_off rte_ixgbevf_stats_strings[] = {
+ {"rx_multicast_packets", offsetof(struct ixgbevf_hw_stats, vfmprc)},
+};
+
+#define IXGBEVF_NB_XSTATS (sizeof(rte_ixgbevf_stats_strings) / \
+ sizeof(rte_ixgbevf_stats_strings[0]))
+
/**
* Atomically reads the link status information from global
* structure rte_eth_dev.
@@ -2431,7 +2442,7 @@ ixgbe_dev_xstats_reset(struct rte_eth_dev *dev)
}

static void
-ixgbevf_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
+ixgbevf_update_stats(struct rte_eth_dev *dev)
{
struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
struct ixgbevf_hw_stats *hw_stats = (struct ixgbevf_hw_stats*)
@@ -2456,8 +2467,44 @@ ixgbevf_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
/* Rx Multicst Packet */
UPDATE_VF_STAT(IXGBE_VFMPRC,
hw_stats->last_vfmprc, hw_stats->vfmprc);
+}

- if (stats == NULL)
+static int
+ixgbevf_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
+ unsigned n)
+{
+ struct ixgbevf_hw_stats *hw_stats = (struct ixgbevf_hw_stats *)
+ IXGBE_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+ unsigned i;
+
+ if(n < IXGBEVF_NB_XSTATS)
+ return IXGBEVF_NB_XSTATS;
+
+ ixgbevf_update_stats(dev);
+
+ if (!xstats)
+ return 0;
+
+ /* 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].value = *(uint64_t *)(((char *)hw_stats) +
+ rte_ixgbevf_stats_strings[i].offset);
+ }
+
+ return IXGBEVF_NB_XSTATS;
+}
+
+static void
+ixgbevf_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
+{
+ struct ixgbevf_hw_stats *hw_stats = (struct ixgbevf_hw_stats *)
+ IXGBE_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+
+ ixgbevf_update_stats(dev);
+
+ if(stats == NULL)
return;

stats->ipackets = hw_stats->vfgprc;
--
1.9.1
Harry van Haaren
2015-10-30 11:36:37 UTC
Permalink
Add implementation of xstats() functions in i40evf PMD.

Signed-off-by: Harry van Haaren <***@intel.com>
---
drivers/net/i40e/i40e_ethdev_vf.c | 89 +++++++++++++++++++++++++++++++++++++--
1 file changed, 86 insertions(+), 3 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
index b694400..3181400 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -112,6 +112,9 @@ static int i40evf_dev_link_update(struct rte_eth_dev *dev,
__rte_unused int wait_to_complete);
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 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);
static void i40evf_vlan_offload_set(struct rte_eth_dev *dev, int mask);
@@ -148,6 +151,30 @@ static int i40evf_dev_rss_hash_conf_get(struct rte_eth_dev *dev,
/* Default hash key buffer for RSS */
static uint32_t rss_key_default[I40E_VFQF_HKEY_MAX_INDEX + 1];

+struct rte_i40evf_xstats_name_off {
+ char name[RTE_ETH_XSTATS_NAME_SIZE];
+ unsigned offset;
+};
+
+static const struct rte_i40evf_xstats_name_off rte_i40evf_stats_strings[] = {
+ {"rx_bytes", offsetof(struct i40e_eth_stats, rx_bytes)},
+ {"rx_unicast_packets", offsetof(struct i40e_eth_stats, rx_unicast)},
+ {"rx_multicast_packets", offsetof(struct i40e_eth_stats, rx_multicast)},
+ {"rx_broadcast_packets", offsetof(struct i40e_eth_stats, rx_broadcast)},
+ {"rx_dropped_packets", offsetof(struct i40e_eth_stats, rx_discards)},
+ {"rx_unknown_protocol_packets", offsetof(struct i40e_eth_stats,
+ rx_unknown_protocol)},
+ {"tx_bytes", offsetof(struct i40e_eth_stats, tx_bytes)},
+ {"tx_unicast_packets", offsetof(struct i40e_eth_stats, tx_bytes)},
+ {"tx_multicast_packets", offsetof(struct i40e_eth_stats, tx_bytes)},
+ {"tx_broadcast_packets", offsetof(struct i40e_eth_stats, tx_bytes)},
+ {"tx_dropped_packets", offsetof(struct i40e_eth_stats, tx_bytes)},
+ {"tx_error_packets", offsetof(struct i40e_eth_stats, tx_bytes)},
+};
+
+#define I40EVF_NB_XSTATS (sizeof(rte_i40evf_stats_strings) / \
+ sizeof(rte_i40evf_stats_strings[0]))
+
static const struct eth_dev_ops i40evf_eth_dev_ops = {
.dev_configure = i40evf_dev_configure,
.dev_start = i40evf_dev_start,
@@ -158,6 +185,8 @@ static const struct eth_dev_ops i40evf_eth_dev_ops = {
.allmulticast_disable = i40evf_dev_allmulticast_disable,
.link_update = i40evf_dev_link_update,
.stats_get = i40evf_dev_stats_get,
+ .xstats_get = i40evf_dev_xstats_get,
+ .xstats_reset = i40evf_dev_xstats_reset,
.dev_close = i40evf_dev_close,
.dev_infos_get = i40evf_dev_info_get,
.vlan_filter_set = i40evf_vlan_filter_set,
@@ -888,11 +917,10 @@ i40evf_del_mac_addr(struct rte_eth_dev *dev, struct ether_addr *addr)
}

static int
-i40evf_get_statics(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
+i40evf_update_stats(struct rte_eth_dev *dev, struct i40e_eth_stats **pstats)
{
struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
struct i40e_virtchnl_queue_select q_stats;
- struct i40e_eth_stats *pstats;
int err;
struct vf_cmd_info args;

@@ -907,9 +935,23 @@ i40evf_get_statics(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
err = i40evf_execute_vf_cmd(dev, &args);
if (err) {
PMD_DRV_LOG(ERR, "fail to execute command OP_GET_STATS");
+ *pstats = NULL;
return err;
}
- pstats = (struct i40e_eth_stats *)args.out_buffer;
+ *pstats = (struct i40e_eth_stats *)args.out_buffer;
+ return 0;
+}
+
+static int
+i40evf_get_statics(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
+{
+ int ret;
+ struct i40e_eth_stats *pstats = NULL;
+
+ ret = i40evf_update_stats(dev, &pstats);
+ if(ret != 0)
+ return 0;
+
stats->ipackets = pstats->rx_unicast + pstats->rx_multicast +
pstats->rx_broadcast;
stats->opackets = pstats->tx_broadcast + pstats->tx_multicast +
@@ -922,6 +964,47 @@ i40evf_get_statics(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
return 0;
}

+static void
+i40evf_dev_xstats_reset(struct rte_eth_dev *dev)
+{
+ struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
+ struct i40e_eth_stats *pstats = NULL;
+
+ /* read stat values to clear hardware registers */
+ i40evf_update_stats(dev, &pstats);
+
+ /* set stats offset base on current values */
+ vf->vsi.eth_stats_offset = vf->vsi.eth_stats;
+}
+
+static int i40evf_dev_xstats_get(struct rte_eth_dev *dev,
+ struct rte_eth_xstats *xstats, unsigned n)
+{
+ int ret;
+ unsigned i;
+ struct i40e_eth_stats *pstats = NULL;
+
+ if(n < I40EVF_NB_XSTATS)
+ return I40EVF_NB_XSTATS;
+
+ ret = i40evf_update_stats(dev, &pstats);
+ if(ret != 0)
+ return 0;
+
+ if(!xstats)
+ return 0;
+
+ /* 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].value = *(uint64_t *)(((char *)pstats) +
+ rte_i40evf_stats_strings[i].offset);
+ }
+
+ return I40EVF_NB_XSTATS;
+}
+
static int
i40evf_add_vlan(struct rte_eth_dev *dev, uint16_t vlanid)
{
--
1.9.1
Harry van Haaren
2015-10-30 11:36:36 UTC
Permalink
Add xstats functions to i40e PMD, allowing extended statistics
to be retrieved from the NIC and exposed to the DPDK.

Signed-off-by: Harry van Haaren <***@intel.com>
---
drivers/net/i40e/i40e_ethdev.c | 217 +++++++++++++++++++++++++++++++++++++++--
1 file changed, 210 insertions(+), 7 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 2dd9fdc..f3f2e0c 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -127,7 +127,10 @@ static int i40e_dev_set_link_up(struct rte_eth_dev *dev);
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);
static void i40e_dev_stats_reset(struct rte_eth_dev *dev);
+static void i40e_dev_xstats_reset(struct rte_eth_dev *dev);
static int i40e_dev_queue_stats_mapping_set(struct rte_eth_dev *dev,
uint16_t queue_id,
uint8_t stat_idx,
@@ -232,6 +235,8 @@ static int i40e_timesync_read_rx_timestamp(struct rte_eth_dev *dev,
uint32_t flags);
static int i40e_timesync_read_tx_timestamp(struct rte_eth_dev *dev,
struct timespec *timestamp);
+static void i40e_read_stats_registers(struct i40e_pf *pf, struct i40e_hw *hw);
+

static const struct rte_pci_id pci_id_i40e_map[] = {
#define RTE_PCI_DEV_ID_DECL_I40E(vend, dev) {RTE_PCI_DEVICE(vend, dev)},
@@ -252,7 +257,9 @@ static const struct eth_dev_ops i40e_eth_dev_ops = {
.dev_set_link_down = i40e_dev_set_link_down,
.link_update = i40e_dev_link_update,
.stats_get = i40e_dev_stats_get,
+ .xstats_get = i40e_dev_xstats_get,
.stats_reset = i40e_dev_stats_reset,
+ .xstats_reset = i40e_dev_xstats_reset,
.queue_stats_mapping_set = i40e_dev_queue_stats_mapping_set,
.dev_infos_get = i40e_dev_info_get,
.vlan_filter_set = i40e_vlan_filter_set,
@@ -291,6 +298,101 @@ static const struct eth_dev_ops i40e_eth_dev_ops = {
.timesync_read_tx_timestamp = i40e_timesync_read_tx_timestamp,
};

+/* store statistics names and its offset in stats structure */
+struct rte_i40e_xstats_name_off {
+ char name[RTE_ETH_XSTATS_NAME_SIZE];
+ unsigned offset;
+};
+
+static const struct rte_i40e_xstats_name_off rte_i40e_stats_strings[] = {
+ {"rx_unicast_packets", offsetof(struct i40e_eth_stats, rx_unicast)},
+ {"rx_multicast_packets", offsetof(struct i40e_eth_stats, rx_multicast)},
+ {"rx_broadcast_packets", offsetof(struct i40e_eth_stats, rx_broadcast)},
+ {"rx_dropped", offsetof(struct i40e_eth_stats, rx_discards)},
+ {"rx_unknown_protocol_packets", offsetof(struct i40e_eth_stats,
+ rx_unknown_protocol)},
+ {"tx_unicast_packets", offsetof(struct i40e_eth_stats, tx_unicast)},
+ {"tx_multicast_packets", offsetof(struct i40e_eth_stats, tx_multicast)},
+ {"tx_broadcast_packets", offsetof(struct i40e_eth_stats, tx_broadcast)},
+ {"tx_dropped", offsetof(struct i40e_eth_stats, tx_discards)},
+};
+
+static const struct rte_i40e_xstats_name_off rte_i40e_hw_port_strings[] = {
+ {"tx_link_down_dropped", offsetof(struct i40e_hw_port_stats,
+ tx_dropped_link_down)},
+ {"rx_crc_errors", offsetof(struct i40e_hw_port_stats, crc_errors)},
+ {"rx_illegal_byte_errors", offsetof(struct i40e_hw_port_stats,
+ illegal_bytes)},
+ {"rx_error_bytes", offsetof(struct i40e_hw_port_stats, error_bytes)},
+ {"mac_local_errors", offsetof(struct i40e_hw_port_stats,
+ mac_local_faults)},
+ {"mac_remote_errors", offsetof(struct i40e_hw_port_stats,
+ mac_remote_faults)},
+ {"rx_length_errors", offsetof(struct i40e_hw_port_stats,
+ rx_length_errors)},
+ {"tx_xon_packets", offsetof(struct i40e_hw_port_stats, link_xon_tx)},
+ {"rx_xon_packets", offsetof(struct i40e_hw_port_stats, link_xon_rx)},
+ {"tx_xoff_packets", offsetof(struct i40e_hw_port_stats, link_xoff_tx)},
+ {"rx_xoff_packets", offsetof(struct i40e_hw_port_stats, link_xoff_rx)},
+ {"rx_size_64_packets", offsetof(struct i40e_hw_port_stats, rx_size_64)},
+ {"rx_size_65_to_127_packets", offsetof(struct i40e_hw_port_stats,
+ rx_size_127)},
+ {"rx_size_128_to_255_packets", offsetof(struct i40e_hw_port_stats,
+ rx_size_255)},
+ {"rx_size_256_to_511_packets", offsetof(struct i40e_hw_port_stats,
+ rx_size_511)},
+ {"rx_size_512_to_1023_packets", offsetof(struct i40e_hw_port_stats,
+ rx_size_1023)},
+ {"rx_size_1024_to_1522_packets", offsetof(struct i40e_hw_port_stats,
+ rx_size_1522)},
+ {"rx_size_1523_to_max_packets", offsetof(struct i40e_hw_port_stats,
+ rx_size_big)},
+ {"rx_undersized_errors", offsetof(struct i40e_hw_port_stats,
+ rx_undersize)},
+ {"rx_oversize_errors", offsetof(struct i40e_hw_port_stats,
+ rx_oversize)},
+ {"rx_mac_short_dropped", offsetof(struct i40e_hw_port_stats,
+ mac_short_packet_dropped)},
+ {"rx_fragmented_errors", offsetof(struct i40e_hw_port_stats,
+ rx_fragments)},
+ {"rx_jabber_errors", offsetof(struct i40e_hw_port_stats, rx_jabber)},
+ {"tx_size_64_packets", offsetof(struct i40e_hw_port_stats, tx_size_64)},
+ {"tx_size_65_to_127_packets", offsetof(struct i40e_hw_port_stats,
+ tx_size_127)},
+ {"tx_size_128_to_255_packets", offsetof(struct i40e_hw_port_stats,
+ tx_size_255)},
+ {"tx_size_256_to_511_packets", offsetof(struct i40e_hw_port_stats,
+ tx_size_511)},
+ {"tx_size_512_to_1023_packets", offsetof(struct i40e_hw_port_stats,
+ tx_size_1023)},
+ {"tx_size_1024_to_1522_packets", offsetof(struct i40e_hw_port_stats,
+ tx_size_1522)},
+ {"tx_size_1523_to_max_packets", offsetof(struct i40e_hw_port_stats,
+ tx_size_big)},
+ {"rx_flow_director_atr_match_packets",
+ offsetof(struct i40e_hw_port_stats, fd_atr_match)},
+ {"rx_flow_director_sb_match_packets",
+ offsetof(struct i40e_hw_port_stats, fd_sb_match)},
+ {"tx_low_power_idle_status", offsetof(struct i40e_hw_port_stats,
+ tx_lpi_status)},
+ {"rx_low_power_idle_status", offsetof(struct i40e_hw_port_stats,
+ rx_lpi_status)},
+ {"tx_low_power_idle_count", offsetof(struct i40e_hw_port_stats,
+ tx_lpi_count)},
+ {"rx_low_power_idle_count", offsetof(struct i40e_hw_port_stats,
+ rx_lpi_count)},
+};
+
+/* Q Stats: 5 stats are exposed for each queue, implemented in xstats_get() */
+#define I40E_NB_HW_PORT_Q_STATS (8 * 5)
+
+#define I40E_NB_ETH_XSTATS (sizeof(rte_i40e_stats_strings) / \
+ sizeof(rte_i40e_stats_strings[0]))
+#define I40E_NB_HW_PORT_XSTATS (sizeof(rte_i40e_hw_port_strings) / \
+ sizeof(rte_i40e_hw_port_strings[0]))
+#define I40E_NB_XSTATS (I40E_NB_ETH_XSTATS + I40E_NB_HW_PORT_XSTATS + \
+ I40E_NB_HW_PORT_Q_STATS)
+
static struct eth_driver rte_i40e_pmd = {
.pci_drv = {
.name = "rte_i40e_pmd",
@@ -1322,16 +1424,12 @@ i40e_update_vsi_stats(struct i40e_vsi *vsi)
vsi->vsi_id);
}

-/* Get all statistics of a port */
static void
-i40e_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
+i40e_read_stats_registers(struct i40e_pf *pf, struct i40e_hw *hw)
{
- uint32_t i;
- struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
- struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ unsigned int i;
struct i40e_hw_port_stats *ns = &pf->stats; /* new stats */
struct i40e_hw_port_stats *os = &pf->stats_offset; /* old stats */
-
/* Get statistics of struct i40e_eth_stats */
i40e_stat_update_48(hw, I40E_GLPRT_GORCH(hw->port),
I40E_GLPRT_GORCL(hw->port),
@@ -1508,8 +1606,21 @@ i40e_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)

pf->offset_loaded = true;

- if (pf->main_vsi)
+ if(pf->main_vsi)
i40e_update_vsi_stats(pf->main_vsi);
+}
+
+/* Get all statistics of a port */
+static void
+i40e_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
+{
+ struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ struct i40e_hw_port_stats *ns = &pf->stats; /* new stats */
+ unsigned i;
+
+ /* call read registers - updates values, now write them to struct */
+ i40e_read_stats_registers(pf, hw);

stats->ipackets = ns->eth.rx_unicast + ns->eth.rx_multicast +
ns->eth.rx_broadcast;
@@ -1599,6 +1710,98 @@ i40e_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
PMD_DRV_LOG(DEBUG, "***************** PF stats end ********************");
}

+static void
+i40e_dev_xstats_reset(struct rte_eth_dev *dev)
+{
+ struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ struct i40e_hw_port_stats *hw_stats = &pf->stats;
+
+ /* The hw registers are cleared on read */
+ pf->offset_loaded = false;
+ i40e_read_stats_registers(pf, hw);
+
+ /* reset software counters */
+ memset(hw_stats, 0, sizeof(*hw_stats));
+}
+
+static int
+i40e_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
+ unsigned n)
+{
+ struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ unsigned i, count = 0;
+ struct i40e_hw_port_stats *hw_stats = &pf->stats;
+
+ if (n < I40E_NB_XSTATS)
+ return I40E_NB_XSTATS;
+
+ i40e_read_stats_registers(pf, hw);
+
+ /* Reset */
+ if (xstats == NULL)
+ return 0;
+
+ /* 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].value = *(uint64_t *)(((char *)&hw_stats->eth) +
+ rte_i40e_stats_strings[i].offset);
+ count++;
+ }
+
+ /* 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].value = *(uint64_t *)(((char *)hw_stats) +
+ rte_i40e_hw_port_strings[i].offset);
+ count++;
+ }
+
+ /* Get per-queue stats from i40e_hw_port struct */
+ for (i = 0; i < 8; i++) {
+ snprintf(xstats[count].name, sizeof(xstats[count].name),
+ "rx_q%u_xon_priority_packets", i);
+ xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
+ offsetof(struct i40e_hw_port_stats,
+ priority_xon_rx[i]));
+ count++;
+
+ snprintf(xstats[count].name, sizeof(xstats[count].name),
+ "rx_q%u_xoff_priority_packets", i);
+ xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
+ offsetof(struct i40e_hw_port_stats,
+ priority_xoff_rx[i]));
+ count++;
+
+ snprintf(xstats[count].name, sizeof(xstats[count].name),
+ "tx_q%u_xon_priority_packets", i);
+ xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
+ offsetof(struct i40e_hw_port_stats,
+ priority_xon_tx[i]));
+ count++;
+
+ snprintf(xstats[count].name, sizeof(xstats[count].name),
+ "tx_q%u_xoff_priority_packets", i);
+ xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
+ offsetof(struct i40e_hw_port_stats,
+ priority_xoff_tx[i]));
+ count++;
+
+ snprintf(xstats[count].name, sizeof(xstats[count].name),
+ "xx_q%u_xon_to_xoff_priority_packets", i);
+ xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
+ offsetof(struct i40e_hw_port_stats,
+ priority_xon_2_xoff[i]));
+ count++;
+ }
+
+ return I40E_NB_XSTATS;
+}
+
/* Reset the statistics */
static void
i40e_dev_stats_reset(struct rte_eth_dev *dev)
--
1.9.1
Harry van Haaren
2015-10-30 11:36:38 UTC
Permalink
Add xstats() functions and statistic strings.

Signed-off-by: Harry van Haaren <***@intel.com>
---
drivers/net/fm10k/fm10k_ethdev.c | 87 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 87 insertions(+)

diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c
index b104fc2..533b25e 100644
--- a/drivers/net/fm10k/fm10k_ethdev.c
+++ b/drivers/net/fm10k/fm10k_ethdev.c
@@ -68,6 +68,46 @@ fm10k_MACVLAN_remove_all(struct rte_eth_dev *dev);
static void fm10k_tx_queue_release(void *queue);
static void fm10k_rx_queue_release(void *queue);

+struct fm10k_xstats_name_off {
+ char name[RTE_ETH_XSTATS_NAME_SIZE];
+ unsigned offset;
+};
+
+struct fm10k_xstats_name_off fm10k_hw_stats_strings[] = {
+ {"completion_timeout_count", offsetof(struct fm10k_hw_stats, timeout)},
+ {"unsupported_requests_count", offsetof(struct fm10k_hw_stats, ur)},
+ {"completer_abort_count", offsetof(struct fm10k_hw_stats, ca)},
+ {"unsupported_message_count", offsetof(struct fm10k_hw_stats, um)},
+ {"checksum_error_count", offsetof(struct fm10k_hw_stats, xec)},
+ {"vlan_dropped", offsetof(struct fm10k_hw_stats, vlan_drop)},
+ {"loopback_dropped", offsetof(struct fm10k_hw_stats, loopback_drop)},
+ {"rx_mbuf_allocation_errors", offsetof(struct fm10k_hw_stats,
+ nodesc_drop)},
+};
+
+#define FM10K_NB_HW_XSTATS (sizeof(fm10k_hw_stats_strings) / \
+ sizeof(fm10k_hw_stats_strings[0]))
+
+struct fm10k_xstats_name_off fm10k_hw_stats_rx_q_strings[] = {
+ {"packets", offsetof(struct fm10k_hw_stats_q, rx_packets)},
+ {"bytes", offsetof(struct fm10k_hw_stats_q, rx_bytes)},
+ {"dropped", offsetof(struct fm10k_hw_stats_q, rx_drops)},
+};
+
+#define FM10K_NB_RX_Q_XSTATS (sizeof(fm10k_hw_stats_rx_q_strings) / \
+ sizeof(fm10k_hw_stats_rx_q_strings[0]))
+
+struct fm10k_xstats_name_off fm10k_hw_stats_tx_q_strings[] = {
+ {"packets", offsetof(struct fm10k_hw_stats_q, tx_packets)},
+ {"bytes", offsetof(struct fm10k_hw_stats_q, tx_bytes)},
+};
+
+#define FM10K_NB_TX_Q_XSTATS (sizeof(fm10k_hw_stats_tx_q_strings) / \
+ sizeof(fm10k_hw_stats_tx_q_strings[0]))
+
+#define FM10K_NB_XSTATS (FM10K_NB_HW_XSTATS + FM10K_MAX_QUEUES_PF * \
+ (FM10K_NB_RX_Q_XSTATS + FM10K_NB_TX_Q_XSTATS))
+
static void
fm10k_mbx_initlock(struct fm10k_hw *hw)
{
@@ -867,6 +907,51 @@ fm10k_link_update(struct rte_eth_dev *dev,
return 0;
}

+static int
+fm10k_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
+ unsigned n)
+{
+ struct fm10k_hw_stats *hw_stats =
+ FM10K_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+ unsigned i, q, count = 0;
+
+ if(n < FM10K_NB_XSTATS)
+ return FM10K_NB_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].value = *(uint64_t *)(((char *)hw_stats) +
+ fm10k_hw_stats_strings[count].offset);
+ 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[count].name, sizeof(xstats[count].name),
+ "rx_q%u_%s", q,
+ fm10k_hw_stats_rx_q_strings[i].name);
+ 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].value =
+ *(uint64_t *)(((char *)&hw_stats->q[q]) +
+ fm10k_hw_stats_tx_q_strings[i].offset);
+ count++;
+ }
+ }
+
+ return FM10K_NB_XSTATS;
+}
+
static void
fm10k_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
{
@@ -2035,7 +2120,9 @@ static const struct eth_dev_ops fm10k_eth_dev_ops = {
.allmulticast_enable = fm10k_dev_allmulticast_enable,
.allmulticast_disable = fm10k_dev_allmulticast_disable,
.stats_get = fm10k_stats_get,
+ .xstats_get = fm10k_xstats_get,
.stats_reset = fm10k_stats_reset,
+ .xstats_reset = fm10k_stats_reset,
.link_update = fm10k_link_update,
.dev_infos_get = fm10k_dev_infos_get,
.vlan_filter_set = fm10k_vlan_filter_set,
--
1.9.1
Tahhan, Maryam
2015-10-30 13:21:31 UTC
Permalink
Sent: Friday, October 30, 2015 11:36 AM
Subject: [dpdk-dev] [PATCH v4 00/10] Port XStats
This patchset adds an implementation of the xstats_get() and xstats_reset()
API to the following PMDs: virtio, igb, igbvf, ixgbe, ixgbevf, i40e, i40evf and
fm10k.
The xstats API allows DPDK apps to gain access to extended statistics from
each port on a NIC. These statistics are structured as per a scheme detailed in
the patch for the doc/prog_guide.
v4: Consistency of names, refactored Q stat code
v3: Added more stats to PMDs
v2: Send correct patchset
doc: add extended statistics to prog_guide
ethdev: update xstats_get() strings and Q handling
virtio: add xstats() implementation
igb: add xstats() implementation
igbvf: add xstats() implementation
ixgbe: add extended statistic strings
ixgbevf: add xstats() implementation
i40e: add xstats() implementation
i40evf: add xstats() implementation
fm10k: add xstats() implementation
doc/guides/prog_guide/poll_mode_drv.rst | 51 ++++++-
doc/guides/rel_notes/release_2_2.rst | 14 ++
drivers/net/e1000/igb_ethdev.c | 193 ++++++++++++++++++++++--
drivers/net/fm10k/fm10k_ethdev.c | 87 +++++++++++
drivers/net/i40e/i40e_ethdev.c | 217
++++++++++++++++++++++++++-
drivers/net/i40e/i40e_ethdev_vf.c | 89 ++++++++++-
drivers/net/ixgbe/ixgbe_ethdev.c | 254
+++++++++++++++++++++++++++-----
drivers/net/virtio/virtio_ethdev.c | 98 +++++++++++-
drivers/net/virtio/virtio_rxtx.c | 32 ++++
drivers/net/virtio/virtqueue.h | 4 +
lib/librte_ether/rte_ethdev.c | 38 +++--
11 files changed, 1006 insertions(+), 71 deletions(-)
--
1.9.1
Series-acked-by: Maryam Tahhan <***@intel.com>
Thomas Monjalon
2015-11-02 08:04:11 UTC
Permalink
Harry,
Checkpatch is not happy because you missed the space after the keywords
"if" and "for".
Harry van Haaren
2015-10-22 15:48:25 UTC
Permalink
Add extended statistic section to the programmers
guide, poll mode driver section. This section describes
how the strings stats are formatted, and how the client
code can use this to gather information about the stat.

Signed-off-by: Harry van Haaren <***@intel.com>
---
doc/guides/prog_guide/poll_mode_drv.rst | 51 ++++++++++++++++++++++++++++++++-
1 file changed, 50 insertions(+), 1 deletion(-)

diff --git a/doc/guides/prog_guide/poll_mode_drv.rst b/doc/guides/prog_guide/poll_mode_drv.rst
index 8780ba3..44cc9ce 100644
--- a/doc/guides/prog_guide/poll_mode_drv.rst
+++ b/doc/guides/prog_guide/poll_mode_drv.rst
@@ -1,5 +1,5 @@
.. BSD LICENSE
- Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
All rights reserved.

Redistribution and use in source and binary forms, with or without
@@ -294,3 +294,52 @@ Ethernet Device API
~~~~~~~~~~~~~~~~~~~

The Ethernet device API exported by the Ethernet PMDs is described in the *DPDK API Reference*.
+
+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.
+
+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
+strings split by a single underscore ``_``. The scheme is as follows:
+
+* direction
+* detail 1
+* detail 2
+* detail n
+* unit
+
+Examples of common statistics xstats strings, formatted to comply to the scheme
+proposed above:
+
+* ``rx_bytes``
+* ``rx_crc_errors``
+* ``tx_multicast_packets``
+
+The scheme, although quite simple, allows flexibility in presenting and reading
+information from the statistic strings. The following example illustrates the
+naming scheme:``rx_packets``. In this example, the string is split into two
+components. The first component ``rx`` indicates that the statistic is
+associated with the receive side of the NIC. The second component ``packets``
+indicates that the unit of measure is packets.
+
+A more complicated example: ``tx_size_128_to_255_packets``. In this example,
+``tx`` indicates transmission, ``size`` is the first detail, ``128`` etc are
+more details, and ``packets`` indicates that this is a packet counter.
+
+Some additions in the metadata scheme are as follows:
+
+* If the first part does not match ``rx`` or ``tx``, the statistic does not
+ have an affinity with either recieve of transmit.
+
+* If the first letter of the second part is ``q`` and this ``q`` is followed
+ by a number, this statistic is part of a specific queue.
+
+An example where queue numbers are used is as follows: ``tx_q7_bytes`` which
+indicates this statistic applies to queue number 7, and represents the number
+of transmitted bytes on that queue.
--
1.9.1
Tahhan, Maryam
2015-10-23 14:29:35 UTC
Permalink
Sent: Thursday, October 22, 2015 4:48 PM
Subject: [dpdk-dev] [PATCH v3 02/11] doc: add extended statistics to
prog_guide
Add extended statistic section to the programmers guide, poll mode driver
section. This section describes how the strings stats are formatted, and how
the client code can use this to gather information about the stat.
---
doc/guides/prog_guide/poll_mode_drv.rst | 51
++++++++++++++++++++++++++++++++-
1 file changed, 50 insertions(+), 1 deletion(-)
diff --git a/doc/guides/prog_guide/poll_mode_drv.rst
b/doc/guides/prog_guide/poll_mode_drv.rst
index 8780ba3..44cc9ce 100644
--- a/doc/guides/prog_guide/poll_mode_drv.rst
+++ b/doc/guides/prog_guide/poll_mode_drv.rst
@@ -1,5 +1,5 @@
.. BSD LICENSE
- Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
All rights reserved.
The Ethernet device API exported by the Ethernet PMDs is described in the
*DPDK API Reference*.
+
+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.
+
+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 strings split by a single underscore ``_``. The scheme is
+
+* direction
+* detail 1
+* detail 2
+* detail n
+* unit
+
+Examples of common statistics xstats strings, formatted to comply to
+
+* ``rx_bytes``
+* ``rx_crc_errors``
+* ``tx_multicast_packets``
+
+The scheme, although quite simple, allows flexibility in presenting and
+reading information from the statistic strings. The following example
+illustrates the naming scheme:``rx_packets``. In this example, the
+string is split into two components. The first component ``rx``
+indicates that the statistic is associated with the receive side of the
+NIC. The second component ``packets`` indicates that the unit of measure is
packets.
+
+A more complicated example: ``tx_size_128_to_255_packets``. In this
+example, ``tx`` indicates transmission, ``size`` is the first detail,
+``128`` etc are more details, and ``packets`` indicates that this is a packet
counter.
+
+
+* If the first part does not match ``rx`` or ``tx``, the statistic does
+not
+ have an affinity with either recieve of transmit.
+
+* If the first letter of the second part is ``q`` and this ``q`` is
+followed
+ by a number, this statistic is part of a specific queue.
+
+An example where queue numbers are used is as follows: ``tx_q7_bytes``
+which indicates this statistic applies to queue number 7, and
+represents the number of transmitted bytes on that queue.
--
1.9.1
Acked-by: Maryam Tahhan <***@intel.com>
Harry van Haaren
2015-10-22 15:48:26 UTC
Permalink
Update the strings used for presenting stats to adhere
to the scheme previously presented. Updated xstats_get()
function to handle Q information only if xstats() is not
implemented in the PMD, providing the PMD with the needed
flexibility to expose its extended Q stats.

Signed-off-by: Harry van Haaren <***@intel.com>
---
lib/librte_ether/rte_ethdev.c | 38 +++++++++++++++++++++++---------------
1 file changed, 23 insertions(+), 15 deletions(-)

diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index f593f6e..07f0c26 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -137,27 +137,30 @@ struct rte_eth_xstats_name_off {
};

static const struct rte_eth_xstats_name_off rte_stats_strings[] = {
- {"rx_packets", offsetof(struct rte_eth_stats, ipackets)},
- {"tx_packets", offsetof(struct rte_eth_stats, opackets)},
- {"rx_bytes", offsetof(struct rte_eth_stats, ibytes)},
- {"tx_bytes", offsetof(struct rte_eth_stats, obytes)},
- {"tx_errors", offsetof(struct rte_eth_stats, oerrors)},
+ {"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)},
- {"alloc_rx_buff_failed", offsetof(struct rte_eth_stats, rx_nombuf)},
+ {"tx_errors", offsetof(struct rte_eth_stats, oerrors)},
+ {"rx_mbuf_allocation_errors", offsetof(struct rte_eth_stats,
+ rx_nombuf)},
};
+
#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[] = {
- {"rx_packets", offsetof(struct rte_eth_stats, q_ipackets)},
- {"rx_bytes", offsetof(struct rte_eth_stats, q_ibytes)},
+ {"packets", offsetof(struct rte_eth_stats, q_ipackets)},
+ {"bytes", offsetof(struct rte_eth_stats, q_ibytes)},
+ {"errors", offsetof(struct rte_eth_stats, q_errors)},
};
+
#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[] = {
- {"tx_packets", offsetof(struct rte_eth_stats, q_opackets)},
- {"tx_bytes", offsetof(struct rte_eth_stats, q_obytes)},
- {"tx_errors", offsetof(struct rte_eth_stats, q_errors)},
+ {"packets", offsetof(struct rte_eth_stats, q_opackets)},
+ {"bytes", offsetof(struct rte_eth_stats, q_obytes)},
};
#define RTE_NB_TXQ_STATS (sizeof(rte_txq_stats_strings) / \
sizeof(rte_txq_stats_strings[0]))
@@ -1666,8 +1669,6 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,

/* Return generic statistics */
count = RTE_NB_STATS;
- count += dev->data->nb_rx_queues * RTE_NB_RXQ_STATS;
- count += dev->data->nb_tx_queues * RTE_NB_TXQ_STATS;

/* implemented by the driver */
if (dev->dev_ops->xstats_get != NULL) {
@@ -1679,6 +1680,9 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,

if (xcount < 0)
return xcount;
+ } else {
+ count += dev->data->nb_rx_queues * RTE_NB_RXQ_STATS;
+ count += dev->data->nb_tx_queues * RTE_NB_TXQ_STATS;
}

if (n < count + xcount)
@@ -1698,6 +1702,10 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
xstats[count++].value = val;
}

+ /* if xstats_get() is implemented by the PMD, the Q stats are done */
+ if (dev->dev_ops->xstats_get != NULL)
+ return count + xcount;
+
/* per-rxq stats */
for (q = 0; q < dev->data->nb_rx_queues; q++) {
for (i = 0; i < RTE_NB_RXQ_STATS; i++) {
@@ -1706,7 +1714,7 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
q * sizeof(uint64_t));
val = *stats_ptr;
snprintf(xstats[count].name, sizeof(xstats[count].name),
- "rx_queue_%u_%s", q,
+ "rx_q%u_%s", q,
rte_rxq_stats_strings[i].name);
xstats[count++].value = val;
}
@@ -1720,7 +1728,7 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
q * sizeof(uint64_t));
val = *stats_ptr;
snprintf(xstats[count].name, sizeof(xstats[count].name),
- "tx_queue_%u_%s", q,
+ "tx_q%u_%s", q,
rte_txq_stats_strings[i].name);
xstats[count++].value = val;
}
--
1.9.1
Tahhan, Maryam
2015-10-23 14:35:28 UTC
Permalink
Sent: Thursday, October 22, 2015 4:48 PM
Subject: [dpdk-dev] [PATCH v3 03/11] ethdev: update xstats_get() strings and
Q handling
Update the strings used for presenting stats to adhere to the scheme
previously presented. Updated xstats_get() function to handle Q information
only if xstats() is not implemented in the PMD, providing the PMD with the
needed flexibility to expose its extended Q stats.
---
lib/librte_ether/rte_ethdev.c | 38 +++++++++++++++++++++++---------------
1 file changed, 23 insertions(+), 15 deletions(-)
diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index f593f6e..07f0c26 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -137,27 +137,30 @@ struct rte_eth_xstats_name_off { };
static const struct rte_eth_xstats_name_off rte_stats_strings[] = {
- {"rx_packets", offsetof(struct rte_eth_stats, ipackets)},
- {"tx_packets", offsetof(struct rte_eth_stats, opackets)},
- {"rx_bytes", offsetof(struct rte_eth_stats, ibytes)},
- {"tx_bytes", offsetof(struct rte_eth_stats, obytes)},
- {"tx_errors", offsetof(struct rte_eth_stats, oerrors)},
+ {"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)},
Hi Harry
If there are any apps today scraping the existing stats this will cause an issue.
I think the "good" description breaks the meaning of the various stats defined in the header. For example rx_packets is Total number of successfully received packets rather than the "good" packets.

BR
Maryam
{"rx_errors", offsetof(struct rte_eth_stats, ierrors)},
- {"alloc_rx_buff_failed", offsetof(struct rte_eth_stats, rx_nombuf)},
+ {"tx_errors", offsetof(struct rte_eth_stats, oerrors)},
+ {"rx_mbuf_allocation_errors", offsetof(struct rte_eth_stats,
+ rx_nombuf)},
};
+
#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[] = {
- {"rx_packets", offsetof(struct rte_eth_stats, q_ipackets)},
- {"rx_bytes", offsetof(struct rte_eth_stats, q_ibytes)},
+ {"packets", offsetof(struct rte_eth_stats, q_ipackets)},
+ {"bytes", offsetof(struct rte_eth_stats, q_ibytes)},
+ {"errors", offsetof(struct rte_eth_stats, q_errors)},
};
+
#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[] = {
- {"tx_packets", offsetof(struct rte_eth_stats, q_opackets)},
- {"tx_bytes", offsetof(struct rte_eth_stats, q_obytes)},
- {"tx_errors", offsetof(struct rte_eth_stats, q_errors)},
+ {"packets", offsetof(struct rte_eth_stats, q_opackets)},
+ {"bytes", offsetof(struct rte_eth_stats, q_obytes)},
};
#define RTE_NB_TXQ_STATS (sizeof(rte_txq_stats_strings) / \
sizeof(rte_txq_stats_strings[0]))
@@ -1666,8 +1669,6 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
/* Return generic statistics */
count = RTE_NB_STATS;
- count += dev->data->nb_rx_queues * RTE_NB_RXQ_STATS;
- count += dev->data->nb_tx_queues * RTE_NB_TXQ_STATS;
/* implemented by the driver */
rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
if (xcount < 0)
return xcount;
+ } else {
+ count += dev->data->nb_rx_queues * RTE_NB_RXQ_STATS;
+ count += dev->data->nb_tx_queues * RTE_NB_TXQ_STATS;
}
if (n < count + xcount)
@@ -1698,6 +1702,10 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
xstats[count++].value = val;
}
+ /* if xstats_get() is implemented by the PMD, the Q stats are done */
+ if (dev->dev_ops->xstats_get != NULL)
+ return count + xcount;
+
/* per-rxq stats */
for (q = 0; q < dev->data->nb_rx_queues; q++) {
@@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
q * sizeof(uint64_t));
val = *stats_ptr;
snprintf(xstats[count].name,
sizeof(xstats[count].name),
- "rx_queue_%u_%s", q,
+ "rx_q%u_%s", q,
rte_rxq_stats_strings[i].name);
xstats[count++].value = val;
}
@@ -1720,7 +1728,7 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
q * sizeof(uint64_t));
val = *stats_ptr;
snprintf(xstats[count].name,
sizeof(xstats[count].name),
- "tx_queue_%u_%s", q,
+ "tx_q%u_%s", q,
rte_txq_stats_strings[i].name);
xstats[count++].value = val;
}
--
1.9.1
Tahhan, Maryam
2015-10-23 15:28:31 UTC
Permalink
Sent: Friday, October 23, 2015 3:35 PM
Subject: Re: [dpdk-dev] [PATCH v3 03/11] ethdev: update xstats_get() strings
and Q handling
Sent: Thursday, October 22, 2015 4:48 PM
Subject: [dpdk-dev] [PATCH v3 03/11] ethdev: update xstats_get()
strings and Q handling
Update the strings used for presenting stats to adhere to the scheme
previously presented. Updated xstats_get() function to handle Q
information only if xstats() is not implemented in the PMD, providing
the PMD with the needed flexibility to expose its extended Q stats.
---
lib/librte_ether/rte_ethdev.c | 38
+++++++++++++++++++++++---------------
1 file changed, 23 insertions(+), 15 deletions(-)
diff --git a/lib/librte_ether/rte_ethdev.c
b/lib/librte_ether/rte_ethdev.c index f593f6e..07f0c26 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -137,27 +137,30 @@ struct rte_eth_xstats_name_off { };
static const struct rte_eth_xstats_name_off rte_stats_strings[] = {
- {"rx_packets", offsetof(struct rte_eth_stats, ipackets)},
- {"tx_packets", offsetof(struct rte_eth_stats, opackets)},
- {"rx_bytes", offsetof(struct rte_eth_stats, ibytes)},
- {"tx_bytes", offsetof(struct rte_eth_stats, obytes)},
- {"tx_errors", offsetof(struct rte_eth_stats, oerrors)},
+ {"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)},
Hi Harry
If there are any apps today scraping the existing stats this will cause an issue.
I think the "good" description breaks the meaning of the various stats defined
in the header. For example rx_packets is Total number of successfully
received packets rather than the "good" packets.
BR
Maryam
{"rx_errors", offsetof(struct rte_eth_stats, ierrors)},
My bad, was quoting the wrong stats register... I'm happy with this change

<snip>
Tahhan, Maryam
2015-10-23 15:28:56 UTC
Permalink
Sent: Thursday, October 22, 2015 4:48 PM
Subject: [dpdk-dev] [PATCH v3 03/11] ethdev: update xstats_get() strings and
Q handling
Update the strings used for presenting stats to adhere to the scheme
previously presented. Updated xstats_get() function to handle Q information
only if xstats() is not implemented in the PMD, providing the PMD with the
needed flexibility to expose its extended Q stats.
Acked-by: Maryam Tahhan <***@intel.com>
Harry van Haaren
2015-10-22 15:48:27 UTC
Permalink
Add xstats() functions and statistic strings to virtio PMD.

Signed-off-by: Harry van Haaren <***@intel.com>
---
drivers/net/virtio/virtio_ethdev.c | 98 +++++++++++++++++++++++++++++++++++++-
drivers/net/virtio/virtio_rxtx.c | 32 +++++++++++++
drivers/net/virtio/virtqueue.h | 4 ++
3 files changed, 132 insertions(+), 2 deletions(-)

diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c
index 02f698a..c97d6e9 100644
--- a/drivers/net/virtio/virtio_ethdev.c
+++ b/drivers/net/virtio/virtio_ethdev.c
@@ -80,7 +80,10 @@ static int virtio_dev_link_update(struct rte_eth_dev *dev,
static void virtio_set_hwaddr(struct virtio_hw *hw);
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 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 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,
@@ -109,6 +112,31 @@ static const struct rte_pci_id pci_id_virtio_map[] = {
{ .vendor_id = 0, /* sentinel */ },
};

+struct rte_virtio_xstats_name_off {
+ char name[RTE_ETH_XSTATS_NAME_SIZE];
+ unsigned offset;
+};
+
+/* [rt]x_qX_ is prepended to the name string here */
+static const struct rte_virtio_xstats_name_off rte_virtio_q_stat_strings[] = {
+ {"good_packets", offsetof(struct virtqueue, packets)},
+ {"good_bytes", offsetof(struct virtqueue, bytes)},
+ {"errors", offsetof(struct virtqueue, errors)},
+ {"multicast_packets", offsetof(struct virtqueue, multicast)},
+ {"broadcast_packets", offsetof(struct virtqueue, broadcast)},
+ {"undersize_packets", offsetof(struct virtqueue, size_bins[0])},
+ {"size_64_packets", offsetof(struct virtqueue, size_bins[1])},
+ {"size_65_127_packets", offsetof(struct virtqueue, size_bins[2])},
+ {"size_128_255_packets", offsetof(struct virtqueue, size_bins[3])},
+ {"size_256_511_packets", offsetof(struct virtqueue, size_bins[4])},
+ {"size_512_1023_packets", offsetof(struct virtqueue, size_bins[5])},
+ {"size_1024_1517_packets", offsetof(struct virtqueue, size_bins[6])},
+ {"size_1518_max_packets", offsetof(struct virtqueue, size_bins[7])},
+};
+
+#define VIRTIO_NB_Q_XSTATS (sizeof(rte_virtio_q_stat_strings) / \
+ sizeof(rte_virtio_q_stat_strings[0]))
+
static int
virtio_send_command(struct virtqueue *vq, struct virtio_pmd_ctrl *ctrl,
int *dlen, int pkt_num)
@@ -568,7 +596,9 @@ 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,
.stats_reset = virtio_dev_stats_reset,
+ .xstats_reset = virtio_dev_stats_reset,
.link_update = virtio_dev_link_update,
.rx_queue_setup = virtio_dev_rx_queue_setup,
.rx_queue_release = virtio_dev_rx_queue_release,
@@ -623,7 +653,7 @@ virtio_dev_atomic_write_link_status(struct rte_eth_dev *dev,
}

static void
-virtio_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
+virtio_update_stats(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
{
unsigned i;

@@ -660,6 +690,64 @@ virtio_dev_stats_get(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(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
+ unsigned n)
+{
+ unsigned i;
+ unsigned count = 0;
+
+ unsigned nstats = dev->data->nb_tx_queues * VIRTIO_NB_Q_XSTATS +
+ dev->data->nb_rx_queues * VIRTIO_NB_Q_XSTATS;
+
+ if(n < nstats)
+ return nstats;
+
+ for (i = 0; i < dev->data->nb_rx_queues; i++) {
+ struct virtqueue *rxvq = dev->data->rx_queues[i];
+
+ if(rxvq == NULL)
+ continue;
+
+ 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].value = *(uint64_t *)(((char *)rxvq) +
+ rte_virtio_q_stat_strings[t].offset);
+ count++;
+ }
+ }
+
+ for (i = 0; i < dev->data->nb_tx_queues; i++) {
+ struct virtqueue *txvq = dev->data->tx_queues[i];
+
+ if(txvq == NULL)
+ continue;
+
+ 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].value = *(uint64_t *)(((char *)txvq) +
+ rte_virtio_q_stat_strings[t].offset);
+ count++;
+ }
+ }
+
+ return count;
+}
+
+static void
+virtio_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
+{
+ virtio_update_stats(dev, stats);
+}
+
static void
virtio_dev_stats_reset(struct rte_eth_dev *dev)
{
@@ -673,6 +761,9 @@ virtio_dev_stats_reset(struct rte_eth_dev *dev)
txvq->packets = 0;
txvq->bytes = 0;
txvq->errors = 0;
+ txvq->multicast = 0;
+ txvq->broadcast = 0;
+ memset(txvq->size_bins, 0, sizeof(txvq->size_bins[0]) * 8);
}

for (i = 0; i < dev->data->nb_rx_queues; i++) {
@@ -683,6 +774,9 @@ virtio_dev_stats_reset(struct rte_eth_dev *dev)
rxvq->packets = 0;
rxvq->bytes = 0;
rxvq->errors = 0;
+ rxvq->multicast = 0;
+ rxvq->broadcast = 0;
+ memset(rxvq->size_bins, 0, sizeof(rxvq->size_bins[0]) * 8);
}

dev->data->rx_mbuf_alloc_failed = 0;
diff --git a/drivers/net/virtio/virtio_rxtx.c b/drivers/net/virtio/virtio_rxtx.c
index d35c5f9..a615916 100644
--- a/drivers/net/virtio/virtio_rxtx.c
+++ b/drivers/net/virtio/virtio_rxtx.c
@@ -482,6 +482,34 @@ virtio_discard_rxbuf(struct virtqueue *vq, struct rte_mbuf *m)
}
}

+static void
+virtio_update_packet_stats(struct virtqueue *vq, struct rte_mbuf *mbuf)
+{
+ uint32_t s = mbuf->pkt_len;
+ struct ether_addr *ea;
+
+ if(s == 64) {
+ vq->size_bins[1]++;
+ } else if(s > 64 && s < 1024) {
+ uint32_t bin;
+
+ /* count zeros, and offset into correct bin */
+ bin = (sizeof(s) * 8) - __builtin_clz(s) - 5;
+ vq->size_bins[bin]++;
+ } else {
+ if(s < 64)
+ vq->size_bins[0]++;
+ else if(s < 1519)
+ vq->size_bins[6]++;
+ else if(s >= 1519)
+ vq->size_bins[7]++;
+ }
+
+ ea = rte_pktmbuf_mtod(mbuf, struct ether_addr *);
+ vq->multicast += is_multicast_ether_addr(ea);
+ vq->broadcast += is_broadcast_ether_addr(ea);
+}
+
#define VIRTIO_MBUF_BURST_SZ 64
#define DESC_PER_CACHELINE (RTE_CACHE_LINE_SIZE / sizeof(struct vring_desc))
uint16_t
@@ -543,7 +571,9 @@ virtio_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts)
VIRTIO_DUMP_PACKET(rxm, rxm->data_len);

rx_pkts[nb_rx++] = rxm;
+
rxvq->bytes += rx_pkts[nb_rx - 1]->pkt_len;
+ virtio_update_packet_stats(rxvq, rxm);
}

rxvq->packets += nb_rx;
@@ -706,6 +736,7 @@ virtio_recv_mergeable_pkts(void *rx_queue,
rx_pkts[nb_rx]->data_len);

rxvq->bytes += rx_pkts[nb_rx]->pkt_len;
+ virtio_update_packet_stats(rxvq, rx_pkts[nb_rx]);
nb_rx++;
}

@@ -806,6 +837,7 @@ virtio_xmit_pkts(void *tx_queue, struct rte_mbuf **tx_pkts, uint16_t nb_pkts)
}
nb_tx++;
txvq->bytes += txm->pkt_len;
+ virtio_update_packet_stats(txvq, txm);
} else {
PMD_TX_LOG(ERR, "No free tx descriptors to transmit");
break;
diff --git a/drivers/net/virtio/virtqueue.h b/drivers/net/virtio/virtqueue.h
index 7789411..9032e6d 100644
--- a/drivers/net/virtio/virtqueue.h
+++ b/drivers/net/virtio/virtqueue.h
@@ -194,6 +194,10 @@ struct virtqueue {
uint64_t packets;
uint64_t bytes;
uint64_t errors;
+ uint64_t multicast;
+ uint64_t broadcast;
+ /* Size bins in array as RFC 2819, undersized [0], 64 [1], etc */
+ uint64_t size_bins[8];

struct vq_desc_extra {
void *cookie;
--
1.9.1
Tahhan, Maryam
2015-10-29 16:19:26 UTC
Permalink
Sent: Thursday, October 22, 2015 4:48 PM
Subject: [dpdk-dev] [PATCH v3 04/11] virtio: add xstats() implementation
Add xstats() functions and statistic strings to virtio PMD.
---
Acked-by: Maryam Tahhan <***@intel.com>
Harry van Haaren
2015-10-22 15:48:28 UTC
Permalink
Add xstats_get() and xstats_reset() functions to igb
driver, and the neccessary strings to expose these
NIC statistics.

Signed-off-by: Harry van Haaren <***@intel.com>
---
drivers/net/e1000/igb_ethdev.c | 136 +++++++++++++++++++++++++++++++++++++++--
1 file changed, 131 insertions(+), 5 deletions(-)

diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index 2b081b1..afa4cb4 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -96,7 +96,10 @@ static int eth_igb_link_update(struct rte_eth_dev *dev,
int wait_to_complete);
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 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,
struct rte_eth_dev_info *dev_info);
static void eth_igbvf_infos_get(struct rte_eth_dev *dev,
@@ -292,7 +295,9 @@ static const struct eth_dev_ops eth_igb_ops = {
.allmulticast_disable = eth_igb_allmulticast_disable,
.link_update = eth_igb_link_update,
.stats_get = eth_igb_stats_get,
+ .xstats_get = eth_igb_xstats_get,
.stats_reset = eth_igb_stats_reset,
+ .xstats_reset = eth_igb_xstats_reset,
.dev_infos_get = eth_igb_infos_get,
.mtu_set = eth_igb_mtu_set,
.vlan_filter_set = eth_igb_vlan_filter_set,
@@ -354,6 +359,77 @@ static const struct eth_dev_ops igbvf_eth_dev_ops = {
.get_reg = igbvf_get_regs,
};

+/* store statistics names and its offset in stats structure */
+struct rte_igb_xstats_name_off {
+ char name[RTE_ETH_XSTATS_NAME_SIZE];
+ unsigned offset;
+};
+
+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)},
+ {"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)},
+ {"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)},
+ {"rx_size_512_to_1023_packets", offsetof(struct e1000_hw_stats,
+ prc1023)},
+ {"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_no_buffer_errors", offsetof(struct e1000_hw_stats, rnbc)},
+ {"rx_undersize_packets", offsetof(struct e1000_hw_stats, ruc)},
+ {"rx_fragment_packets", offsetof(struct e1000_hw_stats, rfc)},
+ {"rx_oversize_packets", offsetof(struct e1000_hw_stats, roc)},
+ {"rx_jabber_packets", 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)},
+ {"tx_size_512_to_1023_packets", offsetof(struct e1000_hw_stats,
+ ptc1023)},
+ {"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)},
+};
+
+#define IGB_NB_XSTATS (sizeof(rte_igb_stats_strings) / \
+ sizeof(rte_igb_stats_strings[0]))
+
/**
* Atomically reads the link status information from global
* structure rte_eth_dev.
@@ -1257,11 +1333,8 @@ igb_hardware_init(struct e1000_hw *hw)

/* This function is based on igb_update_stats_counters() in igb/if_igb.c */
static void
-eth_igb_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats)
+igb_read_stats_registers(struct e1000_hw *hw, struct e1000_hw_stats *stats)
{
- struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
- struct e1000_hw_stats *stats =
- E1000_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
int pause_frames;

if(hw->phy.media_type == e1000_media_type_copper ||
@@ -1367,6 +1440,16 @@ eth_igb_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats)
stats->cexterr += E1000_READ_REG(hw, E1000_CEXTERR);
stats->tsctc += E1000_READ_REG(hw, E1000_TSCTC);
stats->tsctfc += E1000_READ_REG(hw, E1000_TSCTFC);
+}
+
+static void
+eth_igb_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats)
+{
+ struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ struct e1000_hw_stats *stats =
+ E1000_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+
+ igb_read_stats_registers(hw, stats);

if (rte_stats == NULL)
return;
@@ -1409,6 +1492,50 @@ eth_igb_stats_reset(struct rte_eth_dev *dev)
}

static void
+eth_igb_xstats_reset(struct rte_eth_dev *dev)
+{
+ struct e1000_hw_stats *stats =
+ E1000_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+
+ /* HW registers are cleared on read */
+ eth_igb_xstats_get(dev, NULL, IGB_NB_XSTATS);
+
+ /* Reset software totals */
+ memset(stats, 0, sizeof(*stats));
+}
+
+static int
+eth_igb_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *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;
+
+ if(n < IGB_NB_XSTATS)
+ return IGB_NB_XSTATS;
+
+ 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++) {
+ snprintf(xstats[i].name, sizeof(xstats[i].name),
+ "%s", rte_igb_stats_strings[i].name);
+ xstats[i].value = *(uint64_t *)(((char *)hw_stats) +
+ rte_igb_stats_strings[i].offset);
+ }
+
+ return IGB_NB_XSTATS;
+}
+
+static void
eth_igbvf_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats)
{
struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
@@ -1463,7 +1590,6 @@ eth_igbvf_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats)
rte_stats->ilbbytes = hw_stats->gorlbc;
rte_stats->olbpackets = hw_stats->gptlbc;
rte_stats->olbbytes = hw_stats->gotlbc;
-
}

static void
--
1.9.1
Tahhan, Maryam
2015-10-23 14:56:50 UTC
Permalink
Sent: Thursday, October 22, 2015 4:48 PM
Subject: [dpdk-dev] [PATCH v3 05/11] igb: add xstats() implementation
Add xstats_get() and xstats_reset() functions to igb driver, and the neccessary
strings to expose these NIC statistics.
Acked-by: Maryam Tahhan <***@intel.com>
Harry van Haaren
2015-10-22 15:48:29 UTC
Permalink
Add xstats functionality to igbvf PMD, adding
necessary statistic strings.

Signed-off-by: Harry van Haaren <***@intel.com>
---
drivers/net/e1000/igb_ethdev.c | 62 +++++++++++++++++++++++++++++++++++++-----
1 file changed, 55 insertions(+), 7 deletions(-)

diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index afa4cb4..1a92caf 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -152,7 +152,10 @@ static int igbvf_dev_start(struct rte_eth_dev *dev);
static void igbvf_dev_stop(struct rte_eth_dev *dev);
static void igbvf_dev_close(struct rte_eth_dev *dev);
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 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 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);
@@ -346,7 +349,9 @@ static const struct eth_dev_ops igbvf_eth_dev_ops = {
.dev_close = igbvf_dev_close,
.link_update = eth_igb_link_update,
.stats_get = eth_igbvf_stats_get,
+ .xstats_get = eth_igbvf_xstats_get,
.stats_reset = eth_igbvf_stats_reset,
+ .xstats_reset = eth_igbvf_stats_reset,
.vlan_filter_set = igbvf_vlan_filter_set,
.dev_infos_get = eth_igbvf_infos_get,
.rx_queue_setup = eth_igb_rx_queue_setup,
@@ -430,6 +435,17 @@ static const struct rte_igb_xstats_name_off rte_igb_stats_strings[] = {
#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)},
+};
+
+#define IGBVF_NB_XSTATS (sizeof(rte_igbvf_stats_strings) / \
+ sizeof(rte_igbvf_stats_strings[0]))
+
/**
* Atomically reads the link status information from global
* structure rte_eth_dev.
@@ -1536,12 +1552,8 @@ eth_igb_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
}

static void
-eth_igbvf_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats)
+igbvf_read_stats_registers(struct e1000_hw *hw, struct e1000_vf_stats *hw_stats)
{
- struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
- struct e1000_vf_stats *hw_stats = (struct e1000_vf_stats*)
- E1000_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
-
/* Good Rx packets, include VF loopback */
UPDATE_VF_STAT(E1000_VFGPRC,
hw_stats->last_gprc, hw_stats->gprc);
@@ -1577,6 +1589,43 @@ eth_igbvf_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats)
/* Good Tx loopback octets */
UPDATE_VF_STAT(E1000_VFGOTLBC,
hw_stats->last_gotlbc, hw_stats->gotlbc);
+}
+
+static int
+eth_igbvf_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
+ unsigned n)
+{
+ struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ struct e1000_vf_stats *hw_stats = (struct e1000_vf_stats *)
+ E1000_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+ unsigned i;
+
+ if(n < IGBVF_NB_XSTATS)
+ return IGBVF_NB_XSTATS;
+
+ igbvf_read_stats_registers(hw, hw_stats);
+
+ if(!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].value = *(uint64_t *)(((char *)hw_stats) +
+ rte_igbvf_stats_strings[i].offset);
+ }
+
+ return IGBVF_NB_XSTATS;
+}
+
+static void
+eth_igbvf_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats)
+{
+ struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ struct e1000_vf_stats *hw_stats = (struct e1000_vf_stats *)
+ E1000_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+
+ igbvf_read_stats_registers(hw, hw_stats);

if (rte_stats == NULL)
return;
@@ -1604,7 +1653,6 @@ eth_igbvf_stats_reset(struct rte_eth_dev *dev)
/* reset HW current stats*/
memset(&hw_stats->gprc, 0, sizeof(*hw_stats) -
offsetof(struct e1000_vf_stats, gprc));
-
}

static void
--
1.9.1
Tahhan, Maryam
2015-10-28 12:17:48 UTC
Permalink
Sent: Thursday, October 22, 2015 4:48 PM
Subject: [dpdk-dev] [PATCH v3 06/11] igbvf: add xstats() implementation
Add xstats functionality to igbvf PMD, adding necessary statistic strings.
---
Acked-by: Maryam Tahhan <***@intel.com>
Harry van Haaren
2015-10-22 15:48:30 UTC
Permalink
Updated and add statistic strings as used by xstats_get().

Signed-off-by: Harry van Haaren <***@intel.com>
---
drivers/net/ixgbe/ixgbe_ethdev.c | 295 ++++++++++++++++++++++++++++++++++++---
1 file changed, 273 insertions(+), 22 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 1e5ffbf..2e9e260 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -506,29 +506,280 @@ struct rte_ixgbe_xstats_name_off {
};

static const struct rte_ixgbe_xstats_name_off rte_ixgbe_stats_strings[] = {
- {"rx_illegal_byte_err", offsetof(struct ixgbe_hw_stats, errbc)},
- {"rx_len_err", offsetof(struct ixgbe_hw_stats, rlec)},
- {"rx_undersize_count", offsetof(struct ixgbe_hw_stats, ruc)},
- {"rx_oversize_count", offsetof(struct ixgbe_hw_stats, roc)},
- {"rx_fragment_count", offsetof(struct ixgbe_hw_stats, rfc)},
- {"rx_jabber_count", offsetof(struct ixgbe_hw_stats, rjc)},
- {"l3_l4_xsum_error", offsetof(struct ixgbe_hw_stats, xec)},
- {"mac_local_fault", offsetof(struct ixgbe_hw_stats, mlfc)},
- {"mac_remote_fault", offsetof(struct ixgbe_hw_stats, mrfc)},
- {"mac_short_pkt_discard", offsetof(struct ixgbe_hw_stats, mspdc)},
- {"fccrc_error", offsetof(struct ixgbe_hw_stats, fccrc)},
- {"fcoe_drop", offsetof(struct ixgbe_hw_stats, fcoerpdc)},
- {"fc_last_error", offsetof(struct ixgbe_hw_stats, fclast)},
- {"rx_broadcast_packets", offsetof(struct ixgbe_hw_stats, bprc)},
- {"rx_phy_multicast_packets", offsetof(struct ixgbe_hw_stats, mprc)},
- {"mgmt_pkts_dropped", offsetof(struct ixgbe_hw_stats, mngpdc)},
{"rx_crc_errors", offsetof(struct ixgbe_hw_stats, crcerrs)},
- {"fdir_match", offsetof(struct ixgbe_hw_stats, fdirmatch)},
- {"fdir_miss", offsetof(struct ixgbe_hw_stats, fdirmiss)},
- {"tx_flow_control_xon", offsetof(struct ixgbe_hw_stats, lxontxc)},
- {"rx_flow_control_xon", offsetof(struct ixgbe_hw_stats, lxonrxc)},
- {"tx_flow_control_xoff", offsetof(struct ixgbe_hw_stats, lxofftxc)},
- {"rx_flow_control_xoff", offsetof(struct ixgbe_hw_stats, lxoffrxc)},
+ {"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_size_512_to_1023_packets", offsetof(struct ixgbe_hw_stats,
+ prc1023)},
+ {"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_managment_packets", offsetof(struct ixgbe_hw_stats, mngprc)},
+ {"rx_managment_dropped", offsetof(struct ixgbe_hw_stats, mngpdc)},
+ {"tx_managment_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)},
+ {"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_discard", offsetof(struct ixgbe_hw_stats, mspdc)},
+ {"rx_l3_l4_xsum_error", offsetof(struct ixgbe_hw_stats, xec)},
+
+ {"flow_director_added_filters", offsetof(struct ixgbe_hw_stats,
+ fdirustat_add)},
+ {"flow_director_removed_filters", offsetof(struct ixgbe_hw_stats,
+ fdirustat_remove)},
+ {"flow_director_filter_add_errors", offsetof(struct ixgbe_hw_stats,
+ fdirfstat_fadd)},
+ {"flow_director_filter_remove_errors", offsetof(struct ixgbe_hw_stats,
+ fdirfstat_fremove)},
+ {"flow_director_matched_filters", offsetof(struct ixgbe_hw_stats,
+ fdirmatch)},
+ {"flow_director_missed_filters", offsetof(struct ixgbe_hw_stats,
+ fdirmiss)},
+
+ {"rx_fcoe_crc_errors", offsetof(struct ixgbe_hw_stats, fccrc)},
+ {"rx_fcoe_dropped", offsetof(struct ixgbe_hw_stats, fcoerpdc)},
+ {"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)},
+ {"rx_fcoe_no_direct_data_placement", offsetof(struct ixgbe_hw_stats,
+ fcoe_noddp)},
+ {"rx_fcoe_no_direct_data_placement_ext_buff",
+ offsetof(struct ixgbe_hw_stats, fcoe_noddp_ext_buff)},
+
+ {"tx_flow_control_xon_packets", offsetof(struct ixgbe_hw_stats,
+ lxontxc)},
+ {"rx_flow_control_xon_packets", offsetof(struct ixgbe_hw_stats,
+ lxonrxc)},
+ {"tx_flow_control_xoff_packets", offsetof(struct ixgbe_hw_stats,
+ lxofftxc)},
+ {"rx_flow_control_xoff_packets", offsetof(struct ixgbe_hw_stats,
+ lxoffrxc)},
+ {"rx_total_missed_packets", offsetof(struct ixgbe_hw_stats, mpctotal)},
+
+ {"rx_q0_missed_packets", offsetof(struct ixgbe_hw_stats, mpc[0])},
+ {"rx_q1_missed_packets", offsetof(struct ixgbe_hw_stats, mpc[1])},
+ {"rx_q2_missed_packets", offsetof(struct ixgbe_hw_stats, mpc[2])},
+ {"rx_q3_missed_packets", offsetof(struct ixgbe_hw_stats, mpc[3])},
+ {"rx_q4_missed_packets", offsetof(struct ixgbe_hw_stats, mpc[4])},
+ {"rx_q5_missed_packets", offsetof(struct ixgbe_hw_stats, mpc[5])},
+ {"rx_q6_missed_packets", offsetof(struct ixgbe_hw_stats, mpc[6])},
+ {"rx_q7_missed_packets", offsetof(struct ixgbe_hw_stats, mpc[7])},
+
+ {"rx_q0_mbuf_allocation_errors", offsetof(struct ixgbe_hw_stats,
+ rnbc[0])},
+ {"rx_q1_mbuf_allocation_errors", offsetof(struct ixgbe_hw_stats,
+ rnbc[1])},
+ {"rx_q2_mbuf_allocation_errors", offsetof(struct ixgbe_hw_stats,
+ rnbc[2])},
+ {"rx_q3_mbuf_allocation_errors", offsetof(struct ixgbe_hw_stats,
+ rnbc[3])},
+ {"rx_q4_mbuf_allocation_errors", offsetof(struct ixgbe_hw_stats,
+ rnbc[4])},
+ {"rx_q5_mbuf_allocation_errors", offsetof(struct ixgbe_hw_stats,
+ rnbc[5])},
+ {"rx_q6_mbuf_allocation_errors", offsetof(struct ixgbe_hw_stats,
+ rnbc[6])},
+ {"rx_q7_mbuf_allocation_errors", offsetof(struct ixgbe_hw_stats,
+ rnbc[7])},
+
+ {"tx_q0_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxontxc[0])},
+ {"tx_q1_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxontxc[1])},
+ {"tx_q2_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxontxc[2])},
+ {"tx_q3_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxontxc[3])},
+ {"tx_q4_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxontxc[4])},
+ {"tx_q5_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxontxc[5])},
+ {"tx_q6_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxontxc[6])},
+ {"tx_q7_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxontxc[7])},
+
+ {"rx_q0_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxonrxc[0])},
+ {"rx_q1_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxonrxc[1])},
+ {"rx_q2_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxonrxc[2])},
+ {"rx_q3_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxonrxc[3])},
+ {"rx_q4_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxonrxc[4])},
+ {"rx_q5_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxonrxc[5])},
+ {"rx_q6_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxonrxc[6])},
+ {"rx_q7_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxonrxc[7])},
+
+ {"tx_q0_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxofftxc[0])},
+ {"tx_q1_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxofftxc[1])},
+ {"tx_q2_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxofftxc[2])},
+ {"tx_q3_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxofftxc[3])},
+ {"tx_q4_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxofftxc[4])},
+ {"tx_q5_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxofftxc[5])},
+ {"tx_q6_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxofftxc[6])},
+ {"tx_q7_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxofftxc[7])},
+
+ {"rx_q0_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxoffrxc[0])},
+ {"rx_q1_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxoffrxc[1])},
+ {"rx_q2_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxoffrxc[2])},
+ {"rx_q3_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxoffrxc[3])},
+ {"rx_q4_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxoffrxc[4])},
+ {"rx_q5_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxoffrxc[5])},
+ {"rx_q6_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxoffrxc[6])},
+ {"rx_q7_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxoffrxc[7])},
+
+ {"xx_q0_xon_to_off_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxon2offc[0])},
+ {"xx_q1_xon_to_off_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxon2offc[1])},
+ {"xx_q2_xon_to_off_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxon2offc[2])},
+ {"xx_q3_xon_to_off_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxon2offc[3])},
+ {"xx_q4_xon_to_off_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxon2offc[4])},
+ {"xx_q5_xon_to_off_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxon2offc[5])},
+ {"xx_q6_xon_to_off_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxon2offc[6])},
+ {"xx_q7_xon_to_off_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxon2offc[7])},
+
+ {"rx_q0_packets", offsetof(struct ixgbe_hw_stats, qprc[0])},
+ {"rx_q1_packets", offsetof(struct ixgbe_hw_stats, qprc[1])},
+ {"rx_q2_packets", offsetof(struct ixgbe_hw_stats, qprc[2])},
+ {"rx_q3_packets", offsetof(struct ixgbe_hw_stats, qprc[3])},
+ {"rx_q4_packets", offsetof(struct ixgbe_hw_stats, qprc[4])},
+ {"rx_q5_packets", offsetof(struct ixgbe_hw_stats, qprc[5])},
+ {"rx_q6_packets", offsetof(struct ixgbe_hw_stats, qprc[6])},
+ {"rx_q7_packets", offsetof(struct ixgbe_hw_stats, qprc[7])},
+ {"rx_q8_packets", offsetof(struct ixgbe_hw_stats, qprc[8])},
+ {"rx_q9_packets", offsetof(struct ixgbe_hw_stats, qprc[9])},
+ {"rx_q10_packets", offsetof(struct ixgbe_hw_stats, qprc[10])},
+ {"rx_q11_packets", offsetof(struct ixgbe_hw_stats, qprc[11])},
+ {"rx_q12_packets", offsetof(struct ixgbe_hw_stats, qprc[12])},
+ {"rx_q13_packets", offsetof(struct ixgbe_hw_stats, qprc[13])},
+ {"rx_q14_packets", offsetof(struct ixgbe_hw_stats, qprc[14])},
+ {"rx_q15_packets", offsetof(struct ixgbe_hw_stats, qprc[15])},
+
+ {"tx_q0_packets", offsetof(struct ixgbe_hw_stats, qptc[0])},
+ {"tx_q1_packets", offsetof(struct ixgbe_hw_stats, qptc[1])},
+ {"tx_q2_packets", offsetof(struct ixgbe_hw_stats, qptc[2])},
+ {"tx_q3_packets", offsetof(struct ixgbe_hw_stats, qptc[3])},
+ {"tx_q4_packets", offsetof(struct ixgbe_hw_stats, qptc[4])},
+ {"tx_q5_packets", offsetof(struct ixgbe_hw_stats, qptc[5])},
+ {"tx_q6_packets", offsetof(struct ixgbe_hw_stats, qptc[6])},
+ {"tx_q7_packets", offsetof(struct ixgbe_hw_stats, qptc[7])},
+ {"tx_q8_packets", offsetof(struct ixgbe_hw_stats, qptc[8])},
+ {"tx_q9_packets", offsetof(struct ixgbe_hw_stats, qptc[9])},
+ {"tx_q10_packets", offsetof(struct ixgbe_hw_stats, qptc[10])},
+ {"tx_q11_packets", offsetof(struct ixgbe_hw_stats, qptc[11])},
+ {"tx_q12_packets", offsetof(struct ixgbe_hw_stats, qptc[12])},
+ {"tx_q13_packets", offsetof(struct ixgbe_hw_stats, qptc[13])},
+ {"tx_q14_packets", offsetof(struct ixgbe_hw_stats, qptc[14])},
+ {"tx_q15_packets", offsetof(struct ixgbe_hw_stats, qptc[15])},
+
+ {"rx_q0_bytes", offsetof(struct ixgbe_hw_stats, qbrc[0])},
+ {"rx_q1_bytes", offsetof(struct ixgbe_hw_stats, qbrc[1])},
+ {"rx_q2_bytes", offsetof(struct ixgbe_hw_stats, qbrc[2])},
+ {"rx_q3_bytes", offsetof(struct ixgbe_hw_stats, qbrc[3])},
+ {"rx_q4_bytes", offsetof(struct ixgbe_hw_stats, qbrc[4])},
+ {"rx_q5_bytes", offsetof(struct ixgbe_hw_stats, qbrc[5])},
+ {"rx_q6_bytes", offsetof(struct ixgbe_hw_stats, qbrc[6])},
+ {"rx_q7_bytes", offsetof(struct ixgbe_hw_stats, qbrc[7])},
+ {"rx_q8_bytes", offsetof(struct ixgbe_hw_stats, qbrc[8])},
+ {"rx_q9_bytes", offsetof(struct ixgbe_hw_stats, qbrc[9])},
+ {"rx_q10_bytes", offsetof(struct ixgbe_hw_stats, qbrc[10])},
+ {"rx_q11_bytes", offsetof(struct ixgbe_hw_stats, qbrc[11])},
+ {"rx_q12_bytes", offsetof(struct ixgbe_hw_stats, qbrc[12])},
+ {"rx_q13_bytes", offsetof(struct ixgbe_hw_stats, qbrc[13])},
+ {"rx_q14_bytes", offsetof(struct ixgbe_hw_stats, qbrc[14])},
+ {"rx_q15_bytes", offsetof(struct ixgbe_hw_stats, qbrc[15])},
+
+ {"tx_q0_bytes", offsetof(struct ixgbe_hw_stats, qbtc[0])},
+ {"tx_q1_bytes", offsetof(struct ixgbe_hw_stats, qbtc[1])},
+ {"tx_q2_bytes", offsetof(struct ixgbe_hw_stats, qbtc[2])},
+ {"tx_q3_bytes", offsetof(struct ixgbe_hw_stats, qbtc[3])},
+ {"tx_q4_bytes", offsetof(struct ixgbe_hw_stats, qbtc[4])},
+ {"tx_q5_bytes", offsetof(struct ixgbe_hw_stats, qbtc[5])},
+ {"tx_q6_bytes", offsetof(struct ixgbe_hw_stats, qbtc[6])},
+ {"tx_q7_bytes", offsetof(struct ixgbe_hw_stats, qbtc[7])},
+ {"tx_q8_bytes", offsetof(struct ixgbe_hw_stats, qbtc[8])},
+ {"tx_q9_bytes", offsetof(struct ixgbe_hw_stats, qbtc[9])},
+ {"tx_q10_bytes", offsetof(struct ixgbe_hw_stats, qbtc[10])},
+ {"tx_q11_bytes", offsetof(struct ixgbe_hw_stats, qbtc[11])},
+ {"tx_q12_bytes", offsetof(struct ixgbe_hw_stats, qbtc[12])},
+ {"tx_q13_bytes", offsetof(struct ixgbe_hw_stats, qbtc[13])},
+ {"tx_q14_bytes", offsetof(struct ixgbe_hw_stats, qbtc[14])},
+ {"tx_q15_bytes", offsetof(struct ixgbe_hw_stats, qbtc[15])},
+
+ {"rx_q0_dropped", offsetof(struct ixgbe_hw_stats, qprdc[0])},
+ {"rx_q1_dropped", offsetof(struct ixgbe_hw_stats, qprdc[1])},
+ {"rx_q2_dropped", offsetof(struct ixgbe_hw_stats, qprdc[2])},
+ {"rx_q3_dropped", offsetof(struct ixgbe_hw_stats, qprdc[3])},
+ {"rx_q4_dropped", offsetof(struct ixgbe_hw_stats, qprdc[4])},
+ {"rx_q5_dropped", offsetof(struct ixgbe_hw_stats, qprdc[5])},
+ {"rx_q6_dropped", offsetof(struct ixgbe_hw_stats, qprdc[6])},
+ {"rx_q7_dropped", offsetof(struct ixgbe_hw_stats, qprdc[7])},
+ {"rx_q8_dropped", offsetof(struct ixgbe_hw_stats, qprdc[8])},
+ {"rx_q9_dropped", offsetof(struct ixgbe_hw_stats, qprdc[9])},
+ {"rx_q10_dropped", offsetof(struct ixgbe_hw_stats, qprdc[10])},
+ {"rx_q11_dropped", offsetof(struct ixgbe_hw_stats, qprdc[11])},
+ {"rx_q12_dropped", offsetof(struct ixgbe_hw_stats, qprdc[12])},
+ {"rx_q13_dropped", offsetof(struct ixgbe_hw_stats, qprdc[13])},
+ {"rx_q14_dropped", offsetof(struct ixgbe_hw_stats, qprdc[14])},
+ {"rx_q15_dropped", offsetof(struct ixgbe_hw_stats, qprdc[15])},
};

#define IXGBE_NB_XSTATS (sizeof(rte_ixgbe_stats_strings) / \
--
1.9.1
Tahhan, Maryam
2015-10-23 14:41:33 UTC
Permalink
Sent: Thursday, October 22, 2015 4:49 PM
Subject: [dpdk-dev] [PATCH v3 07/11] ixgbe: update statistic strings to
scheme
Updated and add statistic strings as used by xstats_get().
---
drivers/net/ixgbe/ixgbe_ethdev.c | 295
++++++++++++++++++++++++++++++++++++---
1 file changed, 273 insertions(+), 22 deletions(-)
diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c
b/drivers/net/ixgbe/ixgbe_ethdev.c
index 1e5ffbf..2e9e260 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -506,29 +506,280 @@ struct rte_ixgbe_xstats_name_off { };
static const struct rte_ixgbe_xstats_name_off rte_ixgbe_stats_strings[] = {
- {"rx_illegal_byte_err", offsetof(struct ixgbe_hw_stats, errbc)},
- {"rx_len_err", offsetof(struct ixgbe_hw_stats, rlec)},
- {"rx_undersize_count", offsetof(struct ixgbe_hw_stats, ruc)},
- {"rx_oversize_count", offsetof(struct ixgbe_hw_stats, roc)},
- {"rx_fragment_count", offsetof(struct ixgbe_hw_stats, rfc)},
- {"rx_jabber_count", offsetof(struct ixgbe_hw_stats, rjc)},
- {"l3_l4_xsum_error", offsetof(struct ixgbe_hw_stats, xec)},
- {"mac_local_fault", offsetof(struct ixgbe_hw_stats, mlfc)},
- {"mac_remote_fault", offsetof(struct ixgbe_hw_stats, mrfc)},
- {"mac_short_pkt_discard", offsetof(struct ixgbe_hw_stats, mspdc)},
- {"fccrc_error", offsetof(struct ixgbe_hw_stats, fccrc)},
- {"fcoe_drop", offsetof(struct ixgbe_hw_stats, fcoerpdc)},
- {"fc_last_error", offsetof(struct ixgbe_hw_stats, fclast)},
- {"rx_broadcast_packets", offsetof(struct ixgbe_hw_stats, bprc)},
- {"rx_phy_multicast_packets", offsetof(struct ixgbe_hw_stats, mprc)},
- {"mgmt_pkts_dropped", offsetof(struct ixgbe_hw_stats, mngpdc)},
{"rx_crc_errors", offsetof(struct ixgbe_hw_stats, crcerrs)},
- {"fdir_match", offsetof(struct ixgbe_hw_stats, fdirmatch)},
- {"fdir_miss", offsetof(struct ixgbe_hw_stats, fdirmiss)},
- {"tx_flow_control_xon", offsetof(struct ixgbe_hw_stats, lxontxc)},
- {"rx_flow_control_xon", offsetof(struct ixgbe_hw_stats, lxonrxc)},
- {"tx_flow_control_xoff", offsetof(struct ixgbe_hw_stats, lxofftxc)},
- {"rx_flow_control_xoff", offsetof(struct ixgbe_hw_stats, lxoffrxc)},
+ {"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_size_512_to_1023_packets", offsetof(struct ixgbe_hw_stats,
+ prc1023)},
+ {"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_managment_packets", offsetof(struct ixgbe_hw_stats, mngprc)},
+ {"rx_managment_dropped", offsetof(struct ixgbe_hw_stats, mngpdc)},
+ {"tx_managment_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)},
+ {"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_discard", offsetof(struct ixgbe_hw_stats, mspdc)},
+ {"rx_l3_l4_xsum_error", offsetof(struct ixgbe_hw_stats, xec)},
+
+ {"flow_director_added_filters", offsetof(struct ixgbe_hw_stats,
+ fdirustat_add)},
+ {"flow_director_removed_filters", offsetof(struct ixgbe_hw_stats,
+ fdirustat_remove)},
+ {"flow_director_filter_add_errors", offsetof(struct ixgbe_hw_stats,
+ fdirfstat_fadd)},
+ {"flow_director_filter_remove_errors", offsetof(struct
ixgbe_hw_stats,
+ fdirfstat_fremove)},
+ {"flow_director_matched_filters", offsetof(struct ixgbe_hw_stats,
+ fdirmatch)},
+ {"flow_director_missed_filters", offsetof(struct ixgbe_hw_stats,
+ fdirmiss)},
+
+ {"rx_fcoe_crc_errors", offsetof(struct ixgbe_hw_stats, fccrc)},
+ {"rx_fcoe_dropped", offsetof(struct ixgbe_hw_stats, fcoerpdc)},
+ {"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)},
+ {"rx_fcoe_no_direct_data_placement", offsetof(struct
ixgbe_hw_stats,
+ fcoe_noddp)},
+ {"rx_fcoe_no_direct_data_placement_ext_buff",
+ offsetof(struct ixgbe_hw_stats, fcoe_noddp_ext_buff)},
+
+ {"tx_flow_control_xon_packets", offsetof(struct ixgbe_hw_stats,
+ lxontxc)},
+ {"rx_flow_control_xon_packets", offsetof(struct ixgbe_hw_stats,
+ lxonrxc)},
+ {"tx_flow_control_xoff_packets", offsetof(struct ixgbe_hw_stats,
+ lxofftxc)},
+ {"rx_flow_control_xoff_packets", offsetof(struct ixgbe_hw_stats,
+ lxoffrxc)},
+ {"rx_total_missed_packets", offsetof(struct ixgbe_hw_stats,
+mpctotal)},
+
+ {"rx_q0_missed_packets", offsetof(struct ixgbe_hw_stats, mpc[0])},
+ {"rx_q1_missed_packets", offsetof(struct ixgbe_hw_stats, mpc[1])},
+ {"rx_q2_missed_packets", offsetof(struct ixgbe_hw_stats, mpc[2])},
+ {"rx_q3_missed_packets", offsetof(struct ixgbe_hw_stats, mpc[3])},
+ {"rx_q4_missed_packets", offsetof(struct ixgbe_hw_stats, mpc[4])},
+ {"rx_q5_missed_packets", offsetof(struct ixgbe_hw_stats, mpc[5])},
+ {"rx_q6_missed_packets", offsetof(struct ixgbe_hw_stats, mpc[6])},
+ {"rx_q7_missed_packets", offsetof(struct ixgbe_hw_stats, mpc[7])},
+
+ {"rx_q0_mbuf_allocation_errors", offsetof(struct ixgbe_hw_stats,
+ rnbc[0])},
+ {"rx_q1_mbuf_allocation_errors", offsetof(struct ixgbe_hw_stats,
+ rnbc[1])},
+ {"rx_q2_mbuf_allocation_errors", offsetof(struct ixgbe_hw_stats,
+ rnbc[2])},
+ {"rx_q3_mbuf_allocation_errors", offsetof(struct ixgbe_hw_stats,
+ rnbc[3])},
+ {"rx_q4_mbuf_allocation_errors", offsetof(struct ixgbe_hw_stats,
+ rnbc[4])},
+ {"rx_q5_mbuf_allocation_errors", offsetof(struct ixgbe_hw_stats,
+ rnbc[5])},
+ {"rx_q6_mbuf_allocation_errors", offsetof(struct ixgbe_hw_stats,
+ rnbc[6])},
+ {"rx_q7_mbuf_allocation_errors", offsetof(struct ixgbe_hw_stats,
+ rnbc[7])},
+
+ {"tx_q0_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxontxc[0])},
+ {"tx_q1_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxontxc[1])},
+ {"tx_q2_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxontxc[2])},
+ {"tx_q3_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxontxc[3])},
+ {"tx_q4_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxontxc[4])},
+ {"tx_q5_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxontxc[5])},
+ {"tx_q6_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxontxc[6])},
+ {"tx_q7_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxontxc[7])},
+
+ {"rx_q0_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxonrxc[0])},
+ {"rx_q1_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxonrxc[1])},
+ {"rx_q2_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxonrxc[2])},
+ {"rx_q3_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxonrxc[3])},
+ {"rx_q4_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxonrxc[4])},
+ {"rx_q5_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxonrxc[5])},
+ {"rx_q6_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxonrxc[6])},
+ {"rx_q7_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxonrxc[7])},
+
+ {"tx_q0_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxofftxc[0])},
+ {"tx_q1_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxofftxc[1])},
+ {"tx_q2_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxofftxc[2])},
+ {"tx_q3_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxofftxc[3])},
+ {"tx_q4_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxofftxc[4])},
+ {"tx_q5_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxofftxc[5])},
+ {"tx_q6_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxofftxc[6])},
+ {"tx_q7_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxofftxc[7])},
+
+ {"rx_q0_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxoffrxc[0])},
+ {"rx_q1_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxoffrxc[1])},
+ {"rx_q2_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxoffrxc[2])},
+ {"rx_q3_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxoffrxc[3])},
+ {"rx_q4_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxoffrxc[4])},
+ {"rx_q5_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxoffrxc[5])},
+ {"rx_q6_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxoffrxc[6])},
+ {"rx_q7_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxoffrxc[7])},
+
+ {"xx_q0_xon_to_off_priority_packets", offsetof(struct
ixgbe_hw_stats,
+ pxon2offc[0])},
+ {"xx_q1_xon_to_off_priority_packets", offsetof(struct
ixgbe_hw_stats,
+ pxon2offc[1])},
+ {"xx_q2_xon_to_off_priority_packets", offsetof(struct
ixgbe_hw_stats,
+ pxon2offc[2])},
+ {"xx_q3_xon_to_off_priority_packets", offsetof(struct
ixgbe_hw_stats,
+ pxon2offc[3])},
+ {"xx_q4_xon_to_off_priority_packets", offsetof(struct
ixgbe_hw_stats,
+ pxon2offc[4])},
+ {"xx_q5_xon_to_off_priority_packets", offsetof(struct
ixgbe_hw_stats,
+ pxon2offc[5])},
+ {"xx_q6_xon_to_off_priority_packets", offsetof(struct
ixgbe_hw_stats,
+ pxon2offc[6])},
+ {"xx_q7_xon_to_off_priority_packets", offsetof(struct
ixgbe_hw_stats,
+ pxon2offc[7])},
+
+ {"rx_q0_packets", offsetof(struct ixgbe_hw_stats, qprc[0])},
+ {"rx_q1_packets", offsetof(struct ixgbe_hw_stats, qprc[1])},
+ {"rx_q2_packets", offsetof(struct ixgbe_hw_stats, qprc[2])},
+ {"rx_q3_packets", offsetof(struct ixgbe_hw_stats, qprc[3])},
+ {"rx_q4_packets", offsetof(struct ixgbe_hw_stats, qprc[4])},
+ {"rx_q5_packets", offsetof(struct ixgbe_hw_stats, qprc[5])},
+ {"rx_q6_packets", offsetof(struct ixgbe_hw_stats, qprc[6])},
+ {"rx_q7_packets", offsetof(struct ixgbe_hw_stats, qprc[7])},
+ {"rx_q8_packets", offsetof(struct ixgbe_hw_stats, qprc[8])},
+ {"rx_q9_packets", offsetof(struct ixgbe_hw_stats, qprc[9])},
+ {"rx_q10_packets", offsetof(struct ixgbe_hw_stats, qprc[10])},
+ {"rx_q11_packets", offsetof(struct ixgbe_hw_stats, qprc[11])},
+ {"rx_q12_packets", offsetof(struct ixgbe_hw_stats, qprc[12])},
+ {"rx_q13_packets", offsetof(struct ixgbe_hw_stats, qprc[13])},
+ {"rx_q14_packets", offsetof(struct ixgbe_hw_stats, qprc[14])},
+ {"rx_q15_packets", offsetof(struct ixgbe_hw_stats, qprc[15])},
+
+ {"tx_q0_packets", offsetof(struct ixgbe_hw_stats, qptc[0])},
+ {"tx_q1_packets", offsetof(struct ixgbe_hw_stats, qptc[1])},
+ {"tx_q2_packets", offsetof(struct ixgbe_hw_stats, qptc[2])},
+ {"tx_q3_packets", offsetof(struct ixgbe_hw_stats, qptc[3])},
+ {"tx_q4_packets", offsetof(struct ixgbe_hw_stats, qptc[4])},
+ {"tx_q5_packets", offsetof(struct ixgbe_hw_stats, qptc[5])},
+ {"tx_q6_packets", offsetof(struct ixgbe_hw_stats, qptc[6])},
+ {"tx_q7_packets", offsetof(struct ixgbe_hw_stats, qptc[7])},
+ {"tx_q8_packets", offsetof(struct ixgbe_hw_stats, qptc[8])},
+ {"tx_q9_packets", offsetof(struct ixgbe_hw_stats, qptc[9])},
+ {"tx_q10_packets", offsetof(struct ixgbe_hw_stats, qptc[10])},
+ {"tx_q11_packets", offsetof(struct ixgbe_hw_stats, qptc[11])},
+ {"tx_q12_packets", offsetof(struct ixgbe_hw_stats, qptc[12])},
+ {"tx_q13_packets", offsetof(struct ixgbe_hw_stats, qptc[13])},
+ {"tx_q14_packets", offsetof(struct ixgbe_hw_stats, qptc[14])},
+ {"tx_q15_packets", offsetof(struct ixgbe_hw_stats, qptc[15])},
+
+ {"rx_q0_bytes", offsetof(struct ixgbe_hw_stats, qbrc[0])},
+ {"rx_q1_bytes", offsetof(struct ixgbe_hw_stats, qbrc[1])},
+ {"rx_q2_bytes", offsetof(struct ixgbe_hw_stats, qbrc[2])},
+ {"rx_q3_bytes", offsetof(struct ixgbe_hw_stats, qbrc[3])},
+ {"rx_q4_bytes", offsetof(struct ixgbe_hw_stats, qbrc[4])},
+ {"rx_q5_bytes", offsetof(struct ixgbe_hw_stats, qbrc[5])},
+ {"rx_q6_bytes", offsetof(struct ixgbe_hw_stats, qbrc[6])},
+ {"rx_q7_bytes", offsetof(struct ixgbe_hw_stats, qbrc[7])},
+ {"rx_q8_bytes", offsetof(struct ixgbe_hw_stats, qbrc[8])},
+ {"rx_q9_bytes", offsetof(struct ixgbe_hw_stats, qbrc[9])},
+ {"rx_q10_bytes", offsetof(struct ixgbe_hw_stats, qbrc[10])},
+ {"rx_q11_bytes", offsetof(struct ixgbe_hw_stats, qbrc[11])},
+ {"rx_q12_bytes", offsetof(struct ixgbe_hw_stats, qbrc[12])},
+ {"rx_q13_bytes", offsetof(struct ixgbe_hw_stats, qbrc[13])},
+ {"rx_q14_bytes", offsetof(struct ixgbe_hw_stats, qbrc[14])},
+ {"rx_q15_bytes", offsetof(struct ixgbe_hw_stats, qbrc[15])},
+
+ {"tx_q0_bytes", offsetof(struct ixgbe_hw_stats, qbtc[0])},
+ {"tx_q1_bytes", offsetof(struct ixgbe_hw_stats, qbtc[1])},
+ {"tx_q2_bytes", offsetof(struct ixgbe_hw_stats, qbtc[2])},
+ {"tx_q3_bytes", offsetof(struct ixgbe_hw_stats, qbtc[3])},
+ {"tx_q4_bytes", offsetof(struct ixgbe_hw_stats, qbtc[4])},
+ {"tx_q5_bytes", offsetof(struct ixgbe_hw_stats, qbtc[5])},
+ {"tx_q6_bytes", offsetof(struct ixgbe_hw_stats, qbtc[6])},
+ {"tx_q7_bytes", offsetof(struct ixgbe_hw_stats, qbtc[7])},
+ {"tx_q8_bytes", offsetof(struct ixgbe_hw_stats, qbtc[8])},
+ {"tx_q9_bytes", offsetof(struct ixgbe_hw_stats, qbtc[9])},
+ {"tx_q10_bytes", offsetof(struct ixgbe_hw_stats, qbtc[10])},
+ {"tx_q11_bytes", offsetof(struct ixgbe_hw_stats, qbtc[11])},
+ {"tx_q12_bytes", offsetof(struct ixgbe_hw_stats, qbtc[12])},
+ {"tx_q13_bytes", offsetof(struct ixgbe_hw_stats, qbtc[13])},
+ {"tx_q14_bytes", offsetof(struct ixgbe_hw_stats, qbtc[14])},
+ {"tx_q15_bytes", offsetof(struct ixgbe_hw_stats, qbtc[15])},
+
+ {"rx_q0_dropped", offsetof(struct ixgbe_hw_stats, qprdc[0])},
+ {"rx_q1_dropped", offsetof(struct ixgbe_hw_stats, qprdc[1])},
+ {"rx_q2_dropped", offsetof(struct ixgbe_hw_stats, qprdc[2])},
+ {"rx_q3_dropped", offsetof(struct ixgbe_hw_stats, qprdc[3])},
+ {"rx_q4_dropped", offsetof(struct ixgbe_hw_stats, qprdc[4])},
+ {"rx_q5_dropped", offsetof(struct ixgbe_hw_stats, qprdc[5])},
+ {"rx_q6_dropped", offsetof(struct ixgbe_hw_stats, qprdc[6])},
+ {"rx_q7_dropped", offsetof(struct ixgbe_hw_stats, qprdc[7])},
+ {"rx_q8_dropped", offsetof(struct ixgbe_hw_stats, qprdc[8])},
+ {"rx_q9_dropped", offsetof(struct ixgbe_hw_stats, qprdc[9])},
+ {"rx_q10_dropped", offsetof(struct ixgbe_hw_stats, qprdc[10])},
+ {"rx_q11_dropped", offsetof(struct ixgbe_hw_stats, qprdc[11])},
+ {"rx_q12_dropped", offsetof(struct ixgbe_hw_stats, qprdc[12])},
+ {"rx_q13_dropped", offsetof(struct ixgbe_hw_stats, qprdc[13])},
+ {"rx_q14_dropped", offsetof(struct ixgbe_hw_stats, qprdc[14])},
+ {"rx_q15_dropped", offsetof(struct ixgbe_hw_stats, qprdc[15])},
};
#define IXGBE_NB_XSTATS (sizeof(rte_ixgbe_stats_strings) / \
--
1.9.1
Acked-by: Maryam Tahhan <***@intel.com>
Harry van Haaren
2015-10-22 15:48:31 UTC
Permalink
Add xstats() functions and stat strings as necessary to ixgbevf PMD.

Signed-off-by: Harry van Haaren <***@intel.com>
---
drivers/net/ixgbe/ixgbe_ethdev.c | 51 ++++++++++++++++++++++++++++++++++++++--
1 file changed, 49 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 2e9e260..127d168 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -149,6 +149,8 @@ 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);
+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_queue_stats_mapping_set(struct rte_eth_dev *eth_dev,
@@ -477,7 +479,9 @@ static const struct eth_dev_ops ixgbevf_eth_dev_ops = {
.dev_stop = ixgbevf_dev_stop,
.link_update = ixgbe_dev_link_update,
.stats_get = ixgbevf_dev_stats_get,
+ .xstats_get = ixgbevf_dev_xstats_get,
.stats_reset = ixgbevf_dev_stats_reset,
+ .xstats_reset = ixgbevf_dev_stats_reset,
.dev_close = ixgbevf_dev_close,
.dev_infos_get = ixgbevf_dev_info_get,
.mtu_set = ixgbevf_dev_set_mtu,
@@ -785,6 +789,13 @@ static const struct rte_ixgbe_xstats_name_off rte_ixgbe_stats_strings[] = {
#define IXGBE_NB_XSTATS (sizeof(rte_ixgbe_stats_strings) / \
sizeof(rte_ixgbe_stats_strings[0]))

+static const struct rte_ixgbe_xstats_name_off rte_ixgbevf_stats_strings[] = {
+ {"rx_multicast_packets", offsetof(struct ixgbevf_hw_stats, vfmprc)},
+};
+
+#define IXGBEVF_NB_XSTATS (sizeof(rte_ixgbevf_stats_strings) / \
+ sizeof(rte_ixgbevf_stats_strings[0]))
+
/**
* Atomically reads the link status information from global
* structure rte_eth_dev.
@@ -2536,7 +2547,7 @@ ixgbe_dev_xstats_reset(struct rte_eth_dev *dev)
}

static void
-ixgbevf_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
+ixgbevf_update_stats(struct rte_eth_dev *dev)
{
struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
struct ixgbevf_hw_stats *hw_stats = (struct ixgbevf_hw_stats*)
@@ -2561,8 +2572,44 @@ ixgbevf_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
/* Rx Multicst Packet */
UPDATE_VF_STAT(IXGBE_VFMPRC,
hw_stats->last_vfmprc, hw_stats->vfmprc);
+}

- if (stats == NULL)
+static int
+ixgbevf_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
+ unsigned n)
+{
+ struct ixgbevf_hw_stats *hw_stats = (struct ixgbevf_hw_stats *)
+ IXGBE_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+ unsigned i;
+
+ if(n < IXGBEVF_NB_XSTATS)
+ return IXGBEVF_NB_XSTATS;
+
+ ixgbevf_update_stats(dev);
+
+ if (!xstats)
+ return 0;
+
+ /* 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].value = *(uint64_t *)(((char *)hw_stats) +
+ rte_ixgbevf_stats_strings[i].offset);
+ }
+
+ return IXGBEVF_NB_XSTATS;
+}
+
+static void
+ixgbevf_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
+{
+ struct ixgbevf_hw_stats *hw_stats = (struct ixgbevf_hw_stats *)
+ IXGBE_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+
+ ixgbevf_update_stats(dev);
+
+ if(stats == NULL)
return;

stats->ipackets = hw_stats->vfgprc;
--
1.9.1
Tahhan, Maryam
2015-10-28 12:16:47 UTC
Permalink
Sent: Thursday, October 22, 2015 4:49 PM
Subject: [dpdk-dev] [PATCH v3 08/11] ixgbevf: add xstats() functions to VF
Add xstats() functions and stat strings as necessary to ixgbevf PMD.
---
Acked-by: Maryam Tahhan <***@intel.com>
Harry van Haaren
2015-10-22 15:48:32 UTC
Permalink
Add xstats functions to i40e PMD, allowing extended statistics
to be retrieved from the NIC and exposed to the DPDK.

Signed-off-by: Harry van Haaren <***@intel.com>
---
drivers/net/i40e/i40e_ethdev.c | 265 +++++++++++++++++++++++++++++++++++++++--
1 file changed, 258 insertions(+), 7 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 2dd9fdc..cf0199d 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -127,7 +127,10 @@ static int i40e_dev_set_link_up(struct rte_eth_dev *dev);
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);
static void i40e_dev_stats_reset(struct rte_eth_dev *dev);
+static void i40e_dev_xstats_reset(struct rte_eth_dev *dev);
static int i40e_dev_queue_stats_mapping_set(struct rte_eth_dev *dev,
uint16_t queue_id,
uint8_t stat_idx,
@@ -232,6 +235,8 @@ static int i40e_timesync_read_rx_timestamp(struct rte_eth_dev *dev,
uint32_t flags);
static int i40e_timesync_read_tx_timestamp(struct rte_eth_dev *dev,
struct timespec *timestamp);
+static void i40e_read_stats_registers(struct i40e_pf *pf, struct i40e_hw *hw);
+

static const struct rte_pci_id pci_id_i40e_map[] = {
#define RTE_PCI_DEV_ID_DECL_I40E(vend, dev) {RTE_PCI_DEVICE(vend, dev)},
@@ -252,7 +257,9 @@ static const struct eth_dev_ops i40e_eth_dev_ops = {
.dev_set_link_down = i40e_dev_set_link_down,
.link_update = i40e_dev_link_update,
.stats_get = i40e_dev_stats_get,
+ .xstats_get = i40e_dev_xstats_get,
.stats_reset = i40e_dev_stats_reset,
+ .xstats_reset = i40e_dev_xstats_reset,
.queue_stats_mapping_set = i40e_dev_queue_stats_mapping_set,
.dev_infos_get = i40e_dev_info_get,
.vlan_filter_set = i40e_vlan_filter_set,
@@ -291,6 +298,187 @@ static const struct eth_dev_ops i40e_eth_dev_ops = {
.timesync_read_tx_timestamp = i40e_timesync_read_tx_timestamp,
};

+/* store statistics names and its offset in stats structure */
+struct rte_i40e_xstats_name_off {
+ char name[RTE_ETH_XSTATS_NAME_SIZE];
+ unsigned offset;
+};
+
+static const struct rte_i40e_xstats_name_off rte_i40e_stats_strings[] = {
+ {"rx_unicast_packets", offsetof(struct i40e_eth_stats, rx_unicast)},
+ {"rx_multicast_packets", offsetof(struct i40e_eth_stats, rx_multicast)},
+ {"rx_broadcast_packets", offsetof(struct i40e_eth_stats, rx_broadcast)},
+ {"rx_dropped", offsetof(struct i40e_eth_stats, rx_discards)},
+ {"rx_unknown_protocol_packets", offsetof(struct i40e_eth_stats,
+ rx_unknown_protocol)},
+ {"tx_unicast_packets", offsetof(struct i40e_eth_stats, tx_unicast)},
+ {"tx_multicast_packets", offsetof(struct i40e_eth_stats, tx_multicast)},
+ {"tx_broadcast_packets", offsetof(struct i40e_eth_stats, tx_broadcast)},
+ {"tx_dropped", offsetof(struct i40e_eth_stats, tx_discards)},
+};
+
+static const struct rte_i40e_xstats_name_off rte_i40e_hw_port_strings[] = {
+ {"tx_link_down_dropped", offsetof(struct i40e_hw_port_stats,
+ tx_dropped_link_down)},
+ {"rx_crc_errors", offsetof(struct i40e_hw_port_stats, crc_errors)},
+ {"rx_illegal_bytes", offsetof(struct i40e_hw_port_stats,
+ illegal_bytes)},
+ {"rx_error_bytes", offsetof(struct i40e_hw_port_stats, error_bytes)},
+ {"mac_local_errors", offsetof(struct i40e_hw_port_stats,
+ mac_local_faults)},
+ {"mac_remote_errors", offsetof(struct i40e_hw_port_stats,
+ mac_remote_faults)},
+ {"rx_length_errors", offsetof(struct i40e_hw_port_stats,
+ rx_length_errors)},
+ {"tx_xon_packets", offsetof(struct i40e_hw_port_stats, link_xon_tx)},
+ {"rx_xon_packets", offsetof(struct i40e_hw_port_stats, link_xon_rx)},
+ {"tx_xoff_packets", offsetof(struct i40e_hw_port_stats, link_xoff_tx)},
+ {"rx_xoff_packets", offsetof(struct i40e_hw_port_stats, link_xoff_rx)},
+ {"rx_size_64_packets", offsetof(struct i40e_hw_port_stats, rx_size_64)},
+ {"rx_size_65_to_127_packets", offsetof(struct i40e_hw_port_stats,
+ rx_size_127)},
+ {"rx_size_128_to_255_packets", offsetof(struct i40e_hw_port_stats,
+ rx_size_255)},
+ {"rx_size_256_to_511_packets", offsetof(struct i40e_hw_port_stats,
+ rx_size_511)},
+ {"rx_size_512_to_1023_packets", offsetof(struct i40e_hw_port_stats,
+ rx_size_1023)},
+ {"rx_size_1024_to_1522_packets", offsetof(struct i40e_hw_port_stats,
+ rx_size_1522)},
+ {"rx_size_1523_to_max_packets", offsetof(struct i40e_hw_port_stats,
+ rx_size_big)},
+ {"rx_undersized_packets", offsetof(struct i40e_hw_port_stats,
+ rx_undersize)},
+ {"rx_oversize_packets", offsetof(struct i40e_hw_port_stats,
+ rx_oversize)},
+ {"rx_mac_short_dropped", offsetof(struct i40e_hw_port_stats,
+ mac_short_packet_dropped)},
+ {"rx_fragmented_packets", offsetof(struct i40e_hw_port_stats,
+ rx_fragments)},
+ {"rx_jabber_packets", offsetof(struct i40e_hw_port_stats, rx_jabber)},
+ {"tx_size_64_packets", offsetof(struct i40e_hw_port_stats, tx_size_64)},
+ {"tx_size_65_to_127_packets", offsetof(struct i40e_hw_port_stats,
+ tx_size_127)},
+ {"tx_size_128_to_255_packets", offsetof(struct i40e_hw_port_stats,
+ tx_size_255)},
+ {"tx_size_256_to_511_packets", offsetof(struct i40e_hw_port_stats,
+ tx_size_511)},
+ {"tx_size_512_to_1023_packets", offsetof(struct i40e_hw_port_stats,
+ tx_size_1023)},
+ {"tx_size_1024_to_1522_packets", offsetof(struct i40e_hw_port_stats,
+ tx_size_1522)},
+ {"tx_size_1523_to_max_packets", offsetof(struct i40e_hw_port_stats,
+ tx_size_big)},
+ {"rx_flow_director_atr_match_packets",
+ offsetof(struct i40e_hw_port_stats, fd_atr_match)},
+ {"rx_flow_director_sb_match_packets",
+ offsetof(struct i40e_hw_port_stats, fd_sb_match)},
+ {"tx_low_power_idle_status", offsetof(struct i40e_hw_port_stats,
+ tx_lpi_status)},
+ {"rx_low_power_idle_status", offsetof(struct i40e_hw_port_stats,
+ rx_lpi_status)},
+ {"tx_low_power_idle_count", offsetof(struct i40e_hw_port_stats,
+ tx_lpi_count)},
+ {"rx_low_power_idle_count", offsetof(struct i40e_hw_port_stats,
+ rx_lpi_count)},
+
+ /* priority_xon_rx[8] */
+ {"tx_q0_xon_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xon_tx[0])},
+ {"tx_q1_xon_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xon_tx[1])},
+ {"tx_q2_xon_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xon_tx[2])},
+ {"tx_q3_xon_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xon_tx[3])},
+ {"tx_q4_xon_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xon_tx[4])},
+ {"tx_q5_xon_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xon_tx[5])},
+ {"tx_q6_xon_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xon_tx[6])},
+ {"tx_q7_xon_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xon_tx[7])},
+
+ /* priority_xon_rx[8] */
+ {"rx_q0_xon_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xon_rx[0])},
+ {"rx_q1_xon_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xon_rx[1])},
+ {"rx_q2_xon_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xon_rx[2])},
+ {"rx_q3_xon_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xon_rx[3])},
+ {"rx_q4_xon_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xon_rx[4])},
+ {"rx_q5_xon_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xon_rx[5])},
+ {"rx_q6_xon_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xon_rx[6])},
+ {"rx_q7_xon_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xon_rx[7])},
+
+ /* priority_xoff_tx[8] */
+ {"tx_q0_xoff_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xoff_tx[0])},
+ {"tx_q1_xoff_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xoff_tx[1])},
+ {"tx_q2_xoff_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xoff_tx[2])},
+ {"tx_q3_xoff_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xoff_tx[3])},
+ {"tx_q4_xoff_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xoff_tx[4])},
+ {"tx_q5_xoff_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xoff_tx[5])},
+ {"tx_q6_xoff_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xoff_tx[6])},
+ {"tx_q7_xoff_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xoff_tx[7])},
+
+ /* priority_xoff_rx[8] */
+ {"rx_q0_xoff_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xoff_rx[0])},
+ {"rx_q1_xoff_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xoff_rx[1])},
+ {"rx_q2_xoff_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xoff_rx[2])},
+ {"rx_q3_xoff_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xoff_rx[3])},
+ {"rx_q4_xoff_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xoff_rx[4])},
+ {"rx_q5_xoff_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xoff_rx[5])},
+ {"rx_q6_xoff_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xoff_rx[6])},
+ {"rx_q7_xoff_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xoff_rx[7])},
+
+ /* priority_xon_2_xoff[8] */
+ {"xx_q0_xon_to_xoff_priority_packets",
+ offsetof(struct i40e_hw_port_stats, priority_xon_2_xoff[0])},
+ {"xx_q1_xon_to_xoff_priority_packets",
+ offsetof(struct i40e_hw_port_stats, priority_xon_2_xoff[1])},
+ {"xx_q2_xon_to_xoff_priority_packets",
+ offsetof(struct i40e_hw_port_stats, priority_xon_2_xoff[2])},
+ {"xx_q3_xon_to_xoff_priority_packets",
+ offsetof(struct i40e_hw_port_stats, priority_xon_2_xoff[3])},
+ {"xx_q4_xon_to_xoff_priority_packets",
+ offsetof(struct i40e_hw_port_stats, priority_xon_2_xoff[4])},
+ {"xx_q5_xon_to_xoff_priority_packets",
+ offsetof(struct i40e_hw_port_stats, priority_xon_2_xoff[5])},
+ {"xx_q6_xon_to_xoff_priority_packets",
+ offsetof(struct i40e_hw_port_stats, priority_xon_2_xoff[6])},
+ {"xx_q7_xon_to_xoff_priority_packets",
+ offsetof(struct i40e_hw_port_stats, priority_xon_2_xoff[7])},
+};
+
+#define I40E_NB_ETH_XSTATS (sizeof(rte_i40e_stats_strings) / \
+ sizeof(rte_i40e_stats_strings[0]))
+#define I40E_NB_HW_PORT_XSTATS (sizeof(rte_i40e_hw_port_strings) / \
+ sizeof(rte_i40e_hw_port_strings[0]))
+#define I40E_NB_XSTATS (I40E_NB_ETH_XSTATS + I40E_NB_HW_PORT_XSTATS)
+
static struct eth_driver rte_i40e_pmd = {
.pci_drv = {
.name = "rte_i40e_pmd",
@@ -1322,16 +1510,12 @@ i40e_update_vsi_stats(struct i40e_vsi *vsi)
vsi->vsi_id);
}

-/* Get all statistics of a port */
static void
-i40e_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
+i40e_read_stats_registers(struct i40e_pf *pf, struct i40e_hw *hw)
{
- uint32_t i;
- struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
- struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ unsigned int i;
struct i40e_hw_port_stats *ns = &pf->stats; /* new stats */
struct i40e_hw_port_stats *os = &pf->stats_offset; /* old stats */
-
/* Get statistics of struct i40e_eth_stats */
i40e_stat_update_48(hw, I40E_GLPRT_GORCH(hw->port),
I40E_GLPRT_GORCL(hw->port),
@@ -1508,8 +1692,21 @@ i40e_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)

pf->offset_loaded = true;

- if (pf->main_vsi)
+ if(pf->main_vsi)
i40e_update_vsi_stats(pf->main_vsi);
+}
+
+/* Get all statistics of a port */
+static void
+i40e_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
+{
+ struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ struct i40e_hw_port_stats *ns = &pf->stats; /* new stats */
+ unsigned i;
+
+ /* call read registers - updates values, now write them to struct */
+ i40e_read_stats_registers(pf, hw);

stats->ipackets = ns->eth.rx_unicast + ns->eth.rx_multicast +
ns->eth.rx_broadcast;
@@ -1599,6 +1796,60 @@ i40e_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
PMD_DRV_LOG(DEBUG, "***************** PF stats end ********************");
}

+static void
+i40e_dev_xstats_reset(struct rte_eth_dev *dev)
+{
+ struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ struct i40e_hw_port_stats *hw_stats = &pf->stats;
+
+ /* The hw registers are cleared on read */
+ pf->offset_loaded = false;
+ i40e_read_stats_registers(pf, hw);
+
+ /* reset software counters */
+ memset(hw_stats, 0, sizeof(*hw_stats));
+}
+
+static int
+i40e_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
+ unsigned n)
+{
+ struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ unsigned i, count = 0;
+ struct i40e_hw_port_stats *hw_stats = &pf->stats;
+
+ if(n < I40E_NB_XSTATS)
+ return I40E_NB_XSTATS;
+
+ i40e_read_stats_registers(pf, hw);
+
+ /* Reset */
+ if(xstats == NULL)
+ return 0;
+
+ /* copy 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].value = *(uint64_t *)(((char *)&hw_stats->eth) +
+ rte_i40e_stats_strings[i].offset);
+ count++;
+ }
+
+ /* copy 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].value = *(uint64_t *)(((char *)hw_stats) +
+ rte_i40e_hw_port_strings[i].offset);
+ count++;
+ }
+
+ return I40E_NB_XSTATS;
+}
+
/* Reset the statistics */
static void
i40e_dev_stats_reset(struct rte_eth_dev *dev)
--
1.9.1
Tahhan, Maryam
2015-10-23 15:11:00 UTC
Permalink
Sent: Thursday, October 22, 2015 4:49 PM
Subject: [dpdk-dev] [PATCH v3 09/11] i40e: add xstats() implementation
Add xstats functions to i40e PMD, allowing extended statistics to be retrieved
from the NIC and exposed to the DPDK.
Acked-by: Maryam Tahhan <***@intel.com>
Harry van Haaren
2015-10-22 15:48:33 UTC
Permalink
Add implementation of xstats() functions in i40evf PMD.

Signed-off-by: Harry van Haaren <***@intel.com>
---
drivers/net/i40e/i40e_ethdev_vf.c | 89 +++++++++++++++++++++++++++++++++++++--
1 file changed, 86 insertions(+), 3 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
index b694400..3181400 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -112,6 +112,9 @@ static int i40evf_dev_link_update(struct rte_eth_dev *dev,
__rte_unused int wait_to_complete);
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 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);
static void i40evf_vlan_offload_set(struct rte_eth_dev *dev, int mask);
@@ -148,6 +151,30 @@ static int i40evf_dev_rss_hash_conf_get(struct rte_eth_dev *dev,
/* Default hash key buffer for RSS */
static uint32_t rss_key_default[I40E_VFQF_HKEY_MAX_INDEX + 1];

+struct rte_i40evf_xstats_name_off {
+ char name[RTE_ETH_XSTATS_NAME_SIZE];
+ unsigned offset;
+};
+
+static const struct rte_i40evf_xstats_name_off rte_i40evf_stats_strings[] = {
+ {"rx_bytes", offsetof(struct i40e_eth_stats, rx_bytes)},
+ {"rx_unicast_packets", offsetof(struct i40e_eth_stats, rx_unicast)},
+ {"rx_multicast_packets", offsetof(struct i40e_eth_stats, rx_multicast)},
+ {"rx_broadcast_packets", offsetof(struct i40e_eth_stats, rx_broadcast)},
+ {"rx_dropped_packets", offsetof(struct i40e_eth_stats, rx_discards)},
+ {"rx_unknown_protocol_packets", offsetof(struct i40e_eth_stats,
+ rx_unknown_protocol)},
+ {"tx_bytes", offsetof(struct i40e_eth_stats, tx_bytes)},
+ {"tx_unicast_packets", offsetof(struct i40e_eth_stats, tx_bytes)},
+ {"tx_multicast_packets", offsetof(struct i40e_eth_stats, tx_bytes)},
+ {"tx_broadcast_packets", offsetof(struct i40e_eth_stats, tx_bytes)},
+ {"tx_dropped_packets", offsetof(struct i40e_eth_stats, tx_bytes)},
+ {"tx_error_packets", offsetof(struct i40e_eth_stats, tx_bytes)},
+};
+
+#define I40EVF_NB_XSTATS (sizeof(rte_i40evf_stats_strings) / \
+ sizeof(rte_i40evf_stats_strings[0]))
+
static const struct eth_dev_ops i40evf_eth_dev_ops = {
.dev_configure = i40evf_dev_configure,
.dev_start = i40evf_dev_start,
@@ -158,6 +185,8 @@ static const struct eth_dev_ops i40evf_eth_dev_ops = {
.allmulticast_disable = i40evf_dev_allmulticast_disable,
.link_update = i40evf_dev_link_update,
.stats_get = i40evf_dev_stats_get,
+ .xstats_get = i40evf_dev_xstats_get,
+ .xstats_reset = i40evf_dev_xstats_reset,
.dev_close = i40evf_dev_close,
.dev_infos_get = i40evf_dev_info_get,
.vlan_filter_set = i40evf_vlan_filter_set,
@@ -888,11 +917,10 @@ i40evf_del_mac_addr(struct rte_eth_dev *dev, struct ether_addr *addr)
}

static int
-i40evf_get_statics(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
+i40evf_update_stats(struct rte_eth_dev *dev, struct i40e_eth_stats **pstats)
{
struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
struct i40e_virtchnl_queue_select q_stats;
- struct i40e_eth_stats *pstats;
int err;
struct vf_cmd_info args;

@@ -907,9 +935,23 @@ i40evf_get_statics(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
err = i40evf_execute_vf_cmd(dev, &args);
if (err) {
PMD_DRV_LOG(ERR, "fail to execute command OP_GET_STATS");
+ *pstats = NULL;
return err;
}
- pstats = (struct i40e_eth_stats *)args.out_buffer;
+ *pstats = (struct i40e_eth_stats *)args.out_buffer;
+ return 0;
+}
+
+static int
+i40evf_get_statics(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
+{
+ int ret;
+ struct i40e_eth_stats *pstats = NULL;
+
+ ret = i40evf_update_stats(dev, &pstats);
+ if(ret != 0)
+ return 0;
+
stats->ipackets = pstats->rx_unicast + pstats->rx_multicast +
pstats->rx_broadcast;
stats->opackets = pstats->tx_broadcast + pstats->tx_multicast +
@@ -922,6 +964,47 @@ i40evf_get_statics(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
return 0;
}

+static void
+i40evf_dev_xstats_reset(struct rte_eth_dev *dev)
+{
+ struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
+ struct i40e_eth_stats *pstats = NULL;
+
+ /* read stat values to clear hardware registers */
+ i40evf_update_stats(dev, &pstats);
+
+ /* set stats offset base on current values */
+ vf->vsi.eth_stats_offset = vf->vsi.eth_stats;
+}
+
+static int i40evf_dev_xstats_get(struct rte_eth_dev *dev,
+ struct rte_eth_xstats *xstats, unsigned n)
+{
+ int ret;
+ unsigned i;
+ struct i40e_eth_stats *pstats = NULL;
+
+ if(n < I40EVF_NB_XSTATS)
+ return I40EVF_NB_XSTATS;
+
+ ret = i40evf_update_stats(dev, &pstats);
+ if(ret != 0)
+ return 0;
+
+ if(!xstats)
+ return 0;
+
+ /* 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].value = *(uint64_t *)(((char *)pstats) +
+ rte_i40evf_stats_strings[i].offset);
+ }
+
+ return I40EVF_NB_XSTATS;
+}
+
static int
i40evf_add_vlan(struct rte_eth_dev *dev, uint16_t vlanid)
{
--
1.9.1
Tahhan, Maryam
2015-10-28 12:15:34 UTC
Permalink
Sent: Thursday, October 22, 2015 4:49 PM
Subject: [dpdk-dev] [PATCH v3 10/11] i40evf: add xstats() implementation
Add implementation of xstats() functions in i40evf PMD.
---
Acked-by: Maryam Tahhan <***@intel.com>
Harry van Haaren
2015-10-22 15:48:34 UTC
Permalink
Add xstats() functions and statistic strings.

Signed-off-by: Harry van Haaren <***@intel.com>
---
drivers/net/fm10k/fm10k_ethdev.c | 87 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 87 insertions(+)

diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c
index a69c990..acd663c 100644
--- a/drivers/net/fm10k/fm10k_ethdev.c
+++ b/drivers/net/fm10k/fm10k_ethdev.c
@@ -68,6 +68,46 @@ fm10k_MACVLAN_remove_all(struct rte_eth_dev *dev);
static void fm10k_tx_queue_release(void *queue);
static void fm10k_rx_queue_release(void *queue);

+struct fm10k_xstats_name_off {
+ char name[RTE_ETH_XSTATS_NAME_SIZE];
+ unsigned offset;
+};
+
+struct fm10k_xstats_name_off fm10k_hw_stats_strings[] = {
+ {"completion_timeout_count", offsetof(struct fm10k_hw_stats, timeout)},
+ {"unsupported_requests_count", offsetof(struct fm10k_hw_stats, ur)},
+ {"completer_abort_count", offsetof(struct fm10k_hw_stats, ca)},
+ {"unsupported_message_count", offsetof(struct fm10k_hw_stats, um)},
+ {"checksum_error_count", offsetof(struct fm10k_hw_stats, xec)},
+ {"vlan_dropped", offsetof(struct fm10k_hw_stats, vlan_drop)},
+ {"loopback_dropped", offsetof(struct fm10k_hw_stats, loopback_drop)},
+ {"rx_mbuf_allocation_errors", offsetof(struct fm10k_hw_stats,
+ nodesc_drop)},
+};
+
+#define FM10K_NB_HW_XSTATS (sizeof(fm10k_hw_stats_strings) / \
+ sizeof(fm10k_hw_stats_strings[0]))
+
+struct fm10k_xstats_name_off fm10k_hw_stats_rx_q_strings[] = {
+ {"packets", offsetof(struct fm10k_hw_stats_q, rx_packets)},
+ {"bytes", offsetof(struct fm10k_hw_stats_q, rx_bytes)},
+ {"dropped", offsetof(struct fm10k_hw_stats_q, rx_drops)},
+};
+
+#define FM10K_NB_RX_Q_XSTATS (sizeof(fm10k_hw_stats_rx_q_strings) / \
+ sizeof(fm10k_hw_stats_rx_q_strings[0]))
+
+struct fm10k_xstats_name_off fm10k_hw_stats_tx_q_strings[] = {
+ {"packets", offsetof(struct fm10k_hw_stats_q, tx_packets)},
+ {"bytes", offsetof(struct fm10k_hw_stats_q, tx_bytes)},
+};
+
+#define FM10K_NB_TX_Q_XSTATS (sizeof(fm10k_hw_stats_tx_q_strings) / \
+ sizeof(fm10k_hw_stats_tx_q_strings[0]))
+
+#define FM10K_NB_XSTATS (FM10K_NB_HW_XSTATS + FM10K_MAX_QUEUES_PF * \
+ (FM10K_NB_RX_Q_XSTATS + FM10K_NB_TX_Q_XSTATS))
+
static void
fm10k_mbx_initlock(struct fm10k_hw *hw)
{
@@ -867,6 +907,51 @@ fm10k_link_update(struct rte_eth_dev *dev,
return 0;
}

+static int
+fm10k_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
+ unsigned n)
+{
+ struct fm10k_hw_stats *hw_stats =
+ FM10K_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+ unsigned i, q, count = 0;
+
+ if(n < FM10K_NB_XSTATS)
+ return FM10K_NB_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].value = *(uint64_t *)(((char *)hw_stats) +
+ fm10k_hw_stats_strings[count].offset);
+ 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[count].name, sizeof(xstats[count].name),
+ "rx_q%u_%s", q,
+ fm10k_hw_stats_rx_q_strings[i].name);
+ 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].value =
+ *(uint64_t *)(((char *)&hw_stats->q[q]) +
+ fm10k_hw_stats_tx_q_strings[i].offset);
+ count++;
+ }
+ }
+
+ return FM10K_NB_XSTATS;
+}
+
static void
fm10k_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
{
@@ -2034,7 +2119,9 @@ static const struct eth_dev_ops fm10k_eth_dev_ops = {
.allmulticast_enable = fm10k_dev_allmulticast_enable,
.allmulticast_disable = fm10k_dev_allmulticast_disable,
.stats_get = fm10k_stats_get,
+ .xstats_get = fm10k_xstats_get,
.stats_reset = fm10k_stats_reset,
+ .xstats_reset = fm10k_stats_reset,
.link_update = fm10k_link_update,
.dev_infos_get = fm10k_dev_infos_get,
.vlan_filter_set = fm10k_vlan_filter_set,
--
1.9.1
Tahhan, Maryam
2015-10-29 16:41:09 UTC
Permalink
Sent: Thursday, October 22, 2015 4:49 PM
Subject: [dpdk-dev] [PATCH v3 11/11] fm10k: add xstats() implementation
Add xstats() functions and statistic strings.
---
Acked-by: Maryam Tahhan <***@intel.com>
Tom Crugnale
2015-10-28 17:35:09 UTC
Permalink
Hi Harry,

We are planning on using the xstats API for periodic stats collection through a polling thread. This would be done in a generic NIC agnostic manner, which would require that the xstats identifiers have consistent naming amongst all of the NIC types. It would likely be polled several times per second and would only gather a subset of all available xstats types.

I have reviewed your patches and am interested in providing some API enhancements and bugfixes. Are you willing to provide feedback on such changes?

Thank you,
Tom

-----Original Message-----
From: dev [mailto:dev-***@dpdk.org] On Behalf Of Harry van Haaren
Sent: Thursday, October 22, 2015 11:48 AM
To: ***@dpdk.org
Subject: [dpdk-dev] [PATCH v3 00/11] Port XStats

This patchset adds an implementation of the xstats_get() and xstats_reset() API to the following PMDs: virtio, igb, igbvf, ixgbe, ixgbevf, i40e, i40evf and fm10k.

The xstats API allows DPDK apps to gain access to extended statistics from each port on a NIC. These statistics are structured as per a scheme detailed in the patch for the doc/prog_guide.


Harry van Haaren (11):
doc: add extended statistics notes
doc: add extended statistics to prog_guide
ethdev: update xstats_get() strings and Q handling
virtio: add xstats() implementation
igb: add xstats() implementation
igbvf: add xstats() implementation
ixgbe: update statistic strings to scheme
ixgbevf: add xstats() functions to VF
i40e: add xstats() implementation
i40evf: add xstats() implementation
fm10k: add xstats() implementation

doc/guides/prog_guide/poll_mode_drv.rst | 51 ++++-
doc/guides/rel_notes/release_2_2.rst | 12 ++
drivers/net/e1000/igb_ethdev.c | 194 +++++++++++++++++-
drivers/net/fm10k/fm10k_ethdev.c | 87 ++++++++
drivers/net/i40e/i40e_ethdev.c | 265 +++++++++++++++++++++++-
drivers/net/i40e/i40e_ethdev_vf.c | 89 +++++++-
drivers/net/ixgbe/ixgbe_ethdev.c | 346 +++++++++++++++++++++++++++++---
drivers/net/virtio/virtio_ethdev.c | 98 ++++++++-
drivers/net/virtio/virtio_rxtx.c | 32 +++
drivers/net/virtio/virtqueue.h | 4 +
lib/librte_ether/rte_ethdev.c | 38 ++--
11 files changed, 1154 insertions(+), 62 deletions(-)

--
1.9.1
Stephen Hemminger
2015-10-28 21:32:16 UTC
Permalink
On Wed, 28 Oct 2015 17:35:09 +0000
Post by Tom Crugnale
Hi Harry,
We are planning on using the xstats API for periodic stats collection through a polling thread. This would be done in a generic NIC agnostic manner, which would require that the xstats identifiers have consistent naming amongst all of the NIC types. It would likely be polled several times per second and would only gather a subset of all available xstats types.
I have reviewed your patches and am interested in providing some API enhancements and bugfixes. Are you willing to provide feedback on such changes?
Thank you,
Tom
The whole point of xstats is to allow device specific statistics.
Consistent use of names is good from a user interface point of view, but probably
not a hard requirement.
Tom Crugnale
2015-10-29 00:55:33 UTC
Permalink
I understand. Is this the reason that that strings were used to identify the xstat types? An enum type would be much more efficient instead of doing string copies when retrieving the stats, but the number of enum entries would quickly grow out of control as device specific stats were added.

In this case, I'm actually referring to the stats that are common to all NICs. For example, for the received fragmented packets counter, there are three strings that identify this value: rx_fragment_packets (igb), rx_fragment_errors (ixgbe), rx_fragmented_packets (i40e).
I was thinking of making those names consistent. Perhaps the reason why they were different in the first place is that each of the device datasheets refers to these exact names.

Tom

-----Original Message-----
From: Stephen Hemminger [mailto:***@networkplumber.org]
Sent: Wednesday, October 28, 2015 5:32 PM
To: Tom Crugnale
Cc: Harry van Haaren; ***@dpdk.org
Subject: Re: [dpdk-dev] [PATCH v3 00/11] Port XStats

On Wed, 28 Oct 2015 17:35:09 +0000
Post by Tom Crugnale
Hi Harry,
We are planning on using the xstats API for periodic stats collection through a polling thread. This would be done in a generic NIC agnostic manner, which would require that the xstats identifiers have consistent naming amongst all of the NIC types. It would likely be polled several times per second and would only gather a subset of all available xstats types.
I have reviewed your patches and am interested in providing some API enhancements and bugfixes. Are you willing to provide feedback on such changes?
Thank you,
Tom
The whole point of xstats is to allow device specific statistics.
Consistent use of names is good from a user interface point of view, but probably not a hard requirement.
Kyle Larose
2015-10-29 12:55:02 UTC
Permalink
Stephen,

Ultimately the issue we are trying to solve is that there is no device
independent way to get any detailed statistics from NICs controlled by
DPDK. These statistics are quite useful, not just for diagnostics, but
for long term reporting. People using DPDK-based NFV products in a
production environment are not going to be happy that they cannot, for
example, see how the packet size bucket counters varied over time
using some sort of monitoring tool.

The only alternative I can see to providing an API within DPDK is to
build our own abstraction layer triggered off the driver name/pci
ids/etc. I expect other people would end up doing this as well. This
seems like a waste of effort when an abstraction layer already exists
within DPDK.

So, let's consider solving the problem within DPDK. One option is to
use well-defined names for a given xstat that has the same semantics
across NICs, while continuing to allow NICs to expose any stats that
don't fall into this category.

Another option is to provide an API with a well-defined set of stats,
perhaps using an enum. In order for a stat to be added to this list,
it needs to be part of a standard (such as
http://tools.ietf.org/html/rfc2819).

Does anybody else see the need for something like this? We're more
than willing to do the work. We'd like to make sure we have the right
API, though.

Thanks,

Kyle
Post by Tom Crugnale
I understand. Is this the reason that that strings were used to identify the xstat types? An enum type would be much more efficient instead of doing string copies when retrieving the stats, but the number of enum entries would quickly grow out of control as device specific stats were added.
In this case, I'm actually referring to the stats that are common to all NICs. For example, for the received fragmented packets counter, there are three strings that identify this value: rx_fragment_packets (igb), rx_fragment_errors (ixgbe), rx_fragmented_packets (i40e).
I was thinking of making those names consistent. Perhaps the reason why they were different in the first place is that each of the device datasheets refers to these exact names.
Tom
-----Original Message-----
Sent: Wednesday, October 28, 2015 5:32 PM
To: Tom Crugnale
Subject: Re: [dpdk-dev] [PATCH v3 00/11] Port XStats
On Wed, 28 Oct 2015 17:35:09 +0000
Post by Tom Crugnale
Hi Harry,
We are planning on using the xstats API for periodic stats collection through a polling thread. This would be done in a generic NIC agnostic manner, which would require that the xstats identifiers have consistent naming amongst all of the NIC types. It would likely be polled several times per second and would only gather a subset of all available xstats types.
I have reviewed your patches and am interested in providing some API enhancements and bugfixes. Are you willing to provide feedback on such changes?
Thank you,
Tom
The whole point of xstats is to allow device specific statistics.
Consistent use of names is good from a user interface point of view, but probably not a hard requirement.
Thomas Monjalon
2015-10-29 13:10:54 UTC
Permalink
Post by Kyle Larose
Ultimately the issue we are trying to solve is that there is no device
independent way to get any detailed statistics from NICs controlled by
DPDK. These statistics are quite useful, not just for diagnostics, but
for long term reporting. People using DPDK-based NFV products in a
production environment are not going to be happy that they cannot, for
example, see how the packet size bucket counters varied over time
using some sort of monitoring tool.
I don't understand.
The basic statistics are provided in a common API.
The other ones are not available in every NICs and can only be interpreted
while knowing the device. So what is the need exactly?
Do you know an example of a networking layer having this kind of API?
Kyle Larose
2015-10-29 13:57:37 UTC
Permalink
On Thu, Oct 29, 2015 at 9:10 AM, Thomas Monjalon
Post by Thomas Monjalon
I don't understand.
The basic statistics are provided in a common API.
The other ones are not available in every NICs and can only be interpreted
while knowing the device. So what is the need exactly?
The need is to provide information to users about what sort of traffic
is being seen by the device, and why the hardware is behaving the way
it is, leveraging as much as possible the capabilities of the hardware
with minimal effort (i.e. not implementing an abstraction layer at a
higher level).

These are quite useful for diagnosing wider network issues
(configuration, misbehaving devices, dirty fibers/etc). The common API
doesn't expose the more detailed information requested by the various
ethernet mibs. Of course, not all stats are applicable to all devices
(e.g. collisions), but those that are available are still invaluable.
Post by Thomas Monjalon
Do you know an example of a networking layer having this kind of API?
I have worked with SDKs for a few different physical switches and
NPUs. They all provide this sort of API. I think it is quite common
with networking equipment such as routers or switches. These stats
tend to be exposed over SNMP at the very least, and often within local
utilities on the devices themselves.

Thanks,

Kyle
Thomas Monjalon
2015-10-29 14:01:21 UTC
Permalink
Post by Kyle Larose
On Thu, Oct 29, 2015 at 9:10 AM, Thomas Monjalon
Post by Thomas Monjalon
I don't understand.
The basic statistics are provided in a common API.
The other ones are not available in every NICs and can only be interpreted
while knowing the device. So what is the need exactly?
The need is to provide information to users about what sort of traffic
is being seen by the device, and why the hardware is behaving the way
it is, leveraging as much as possible the capabilities of the hardware
with minimal effort (i.e. not implementing an abstraction layer at a
higher level).
These are quite useful for diagnosing wider network issues
(configuration, misbehaving devices, dirty fibers/etc). The common API
doesn't expose the more detailed information requested by the various
ethernet mibs. Of course, not all stats are applicable to all devices
(e.g. collisions), but those that are available are still invaluable.
Thanks for the explanation.
Post by Kyle Larose
Post by Thomas Monjalon
Do you know an example of a networking layer having this kind of API?
I have worked with SDKs for a few different physical switches and
NPUs. They all provide this sort of API. I think it is quite common
with networking equipment such as routers or switches. These stats
tend to be exposed over SNMP at the very least, and often within local
utilities on the devices themselves.
So what is missing currently? Just having a consistent naming of
similar counters?
Kyle Larose
2015-10-29 14:10:29 UTC
Permalink
On Thu, Oct 29, 2015 at 10:01 AM, Thomas Monjalon
Post by Thomas Monjalon
So what is missing currently? Just having a consistent naming of
similar counters?
A consistent naming scheme would certainly solve the problem.

Thanks again,

Kyle
Van Haaren, Harry
2015-10-29 13:17:02 UTC
Permalink
Hi All,

(Please keep everyone on To/CC - a few people were dropped)


Note: During my writing a reply to Kyle, Thomas has also replied to Kyle.
Post by Tom Crugnale
-----Original Message-----
Sent: Thursday, October 29, 2015 12:55 PM
To: Tom Crugnale; Stephen Hemminger
Subject: Re: [dpdk-dev] [PATCH v3 00/11] Port XStats
Ultimately the issue we are trying to solve is that there is no device
independent way to get any detailed statistics from NICs controlled by
DPDK. These statistics are quite useful, not just for diagnostics, but
for long term reporting. People using DPDK-based NFV products in a
production environment are not going to be happy that they cannot, for
example, see how the packet size bucket counters varied over time
using some sort of monitoring tool.
Agreed, and that's what the xstats solves.
Post by Tom Crugnale
So, let's consider solving the problem within DPDK. One option is to
use well-defined names for a given xstat that has the same semantics
across NICs, while continuing to allow NICs to expose any stats that
don't fall into this category.
Yes, this is the aim of the current xstats also. As Tom Crugnale pointed
out, the current implementation has some variation in string names, however
the end-goal is to have consistent naming across NICs.

The scheme for naming stats is described in a doc patch, which was part
of my patchset: http://dpdk.org/dev/patchwork/patch/7906/

Ideally a script will automatically checks stats names against those of
other NICs, allowing switching of NICs and stats remaining consistent.

Given that each NIC is unique, this will require some organization work,
but it seems possible with some collaboration.
Post by Tom Crugnale
Another option is to provide an API with a well-defined set of stats,
perhaps using an enum. In order for a stat to be added to this list,
it needs to be part of a standard (such as
http://tools.ietf.org/html/rfc2819).
I would prefer see xstats gain wider support instead of discussing other
options.
Post by Tom Crugnale
Does anybody else see the need for
Harry van Haaren
2015-09-30 09:40:13 UTC
Permalink
Add extended statistic section to the programmers
guide, poll mode driver section. This section describes
how the strings stats are formatted, and how the client
code can use this to gather information about the stat.

Signed-off-by: Harry van Haaren <***@intel.com>
---
doc/guides/prog_guide/poll_mode_drv.rst | 51 ++++++++++++++++++++++++++++++++-
1 file changed, 50 insertions(+), 1 deletion(-)

diff --git a/doc/guides/prog_guide/poll_mode_drv.rst b/doc/guides/prog_guide/poll_mode_drv.rst
index 8780ba3..44cc9ce 100644
--- a/doc/guides/prog_guide/poll_mode_drv.rst
+++ b/doc/guides/prog_guide/poll_mode_drv.rst
@@ -1,5 +1,5 @@
.. BSD LICENSE
- Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
+ Copyright(c) 2010-2015 Intel Corporation. All rights reserved.
All rights reserved.

Redistribution and use in source and binary forms, with or without
@@ -294,3 +294,52 @@ Ethernet Device API
~~~~~~~~~~~~~~~~~~~

The Ethernet device API exported by the Ethernet PMDs is described in the *DPDK API Reference*.
+
+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.
+
+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
+strings split by a single underscore ``_``. The scheme is as follows:
+
+* direction
+* detail 1
+* detail 2
+* detail n
+* unit
+
+Examples of common statistics xstats strings, formatted to comply to the scheme
+proposed above:
+
+* ``rx_bytes``
+* ``rx_crc_errors``
+* ``tx_multicast_packets``
+
+The scheme, although quite simple, allows flexibility in presenting and reading
+information from the statistic strings. The following example illustrates the
+naming scheme:``rx_packets``. In this example, the string is split into two
+components. The first component ``rx`` indicates that the statistic is
+associated with the receive side of the NIC. The second component ``packets``
+indicates that the unit of measure is packets.
+
+A more complicated example: ``tx_size_128_to_255_packets``. In this example,
+``tx`` indicates transmission, ``size`` is the first detail, ``128`` etc are
+more details, and ``packets`` indicates that this is a packet counter.
+
+Some additions in the metadata scheme are as follows:
+
+* If the first part does not match ``rx`` or ``tx``, the statistic does not
+ have an affinity with either recieve of transmit.
+
+* If the first letter of the second part is ``q`` and this ``q`` is followed
+ by a number, this statistic is part of a specific queue.
+
+An example where queue numbers are used is as follows: ``tx_q7_bytes`` which
+indicates this statistic applies to queue number 7, and represents the number
+of transmitted bytes on that queue.
--
1.9.1
Harry van Haaren
2015-09-30 09:40:14 UTC
Permalink
Update the strings used for presenting stats to adhere
to the scheme previously presented. Updated xstats_get()
function to handle Q information only if xstats() is not
implemented in the PMD, providing the PMD with the needed
flexibility to expose its extended Q stats.

Signed-off-by: Harry van Haaren <***@intel.com>
---
lib/librte_ether/rte_ethdev.c | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/lib/librte_ether/rte_ethdev.c b/lib/librte_ether/rte_ethdev.c
index b309309..4b0184f 100644
--- a/lib/librte_ether/rte_ethdev.c
+++ b/lib/librte_ether/rte_ethdev.c
@@ -143,7 +143,7 @@ static const struct rte_eth_xstats_name_off rte_stats_strings[] = {
{"tx_bytes", offsetof(struct rte_eth_stats, obytes)},
{"tx_errors", offsetof(struct rte_eth_stats, oerrors)},
{"rx_errors", offsetof(struct rte_eth_stats, ierrors)},
- {"alloc_rx_buff_failed", offsetof(struct rte_eth_stats, rx_nombuf)},
+ {"rx_no_mbuf_errors", offsetof(struct rte_eth_stats, rx_nombuf)},
};
#define RTE_NB_STATS (sizeof(rte_stats_strings) / sizeof(rte_stats_strings[0]))

@@ -1666,8 +1666,6 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,

/* Return generic statistics */
count = RTE_NB_STATS;
- count += dev->data->nb_rx_queues * RTE_NB_RXQ_STATS;
- count += dev->data->nb_tx_queues * RTE_NB_TXQ_STATS;

/* implemented by the driver */
if (dev->dev_ops->xstats_get != NULL) {
@@ -1679,6 +1677,9 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,

if (xcount < 0)
return xcount;
+ } else {
+ count += dev->data->nb_rx_queues * RTE_NB_RXQ_STATS;
+ count += dev->data->nb_tx_queues * RTE_NB_TXQ_STATS;
}

if (n < count + xcount)
@@ -1698,6 +1699,10 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
xstats[count++].value = val;
}

+ /* if xstats_get() is implemented by the PMD, the Q stats are done */
+ if (dev->dev_ops->xstats_get != NULL)
+ return count + xcount;
+
/* per-rxq stats */
for (q = 0; q < dev->data->nb_rx_queues; q++) {
for (i = 0; i < RTE_NB_RXQ_STATS; i++) {
@@ -1706,7 +1711,7 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
q * sizeof(uint64_t));
val = *stats_ptr;
snprintf(xstats[count].name, sizeof(xstats[count].name),
- "rx_queue_%u_%s", q,
+ "rx_q%u_%s", q,
rte_rxq_stats_strings[i].name);
xstats[count++].value = val;
}
@@ -1720,7 +1725,7 @@ rte_eth_xstats_get(uint8_t port_id, struct rte_eth_xstats *xstats,
q * sizeof(uint64_t));
val = *stats_ptr;
snprintf(xstats[count].name, sizeof(xstats[count].name),
- "tx_queue_%u_%s", q,
+ "tx_q%u_%s", q,
rte_txq_stats_strings[i].name);
xstats[count++].value = val;
}
--
1.9.1
Harry van Haaren
2015-09-30 09:40:15 UTC
Permalink
Add xstats() functions and statistic strings to virtio PMD.

Signed-off-by: Harry van Haaren <***@intel.com>
---
drivers/net/virtio/virtio_ethdev.c | 82 +++++++++++++++++++++++++++++++++++++-
1 file changed, 80 insertions(+), 2 deletions(-)

diff --git a/drivers/net/virtio/virtio_ethdev.c b/drivers/net/virtio/virtio_ethdev.c
index 465d3cd..c897d1b 100644
--- a/drivers/net/virtio/virtio_ethdev.c
+++ b/drivers/net/virtio/virtio_ethdev.c
@@ -80,7 +80,10 @@ static int virtio_dev_link_update(struct rte_eth_dev *dev,
static void virtio_set_hwaddr(struct virtio_hw *hw);
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 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 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,
@@ -109,6 +112,21 @@ static const struct rte_pci_id pci_id_virtio_map[] = {
{ .vendor_id = 0, /* sentinel */ },
};

+struct rte_virtio_xstats_name_off {
+ char name[RTE_ETH_XSTATS_NAME_SIZE];
+ unsigned offset;
+};
+
+/* [rt]x_qX_ is prepended to the name string here */
+static const struct rte_virtio_xstats_name_off rte_virtio_q_stat_strings[] = {
+ {"packets", offsetof(struct virtqueue, packets)},
+ {"bytes", offsetof(struct virtqueue, bytes)},
+ {"errors", offsetof(struct virtqueue, errors)},
+};
+
+#define VIRTIO_NB_Q_XSTATS (sizeof(rte_virtio_q_stat_strings) / \
+ sizeof(rte_virtio_q_stat_strings[0]))
+
static int
virtio_send_command(struct virtqueue *vq, struct virtio_pmd_ctrl *ctrl,
int *dlen, int pkt_num)
@@ -568,7 +586,9 @@ 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,
.stats_reset = virtio_dev_stats_reset,
+ .xstats_reset = virtio_dev_stats_reset,
.link_update = virtio_dev_link_update,
.rx_queue_setup = virtio_dev_rx_queue_setup,
.rx_queue_release = virtio_dev_rx_queue_release,
@@ -623,7 +643,7 @@ virtio_dev_atomic_write_link_status(struct rte_eth_dev *dev,
}

static void
-virtio_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
+virtio_update_stats(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
{
unsigned i;

@@ -660,6 +680,64 @@ virtio_dev_stats_get(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(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
+ unsigned n)
+{
+ unsigned i;
+ unsigned count = 0;
+
+ unsigned nstats = dev->data->nb_tx_queues * VIRTIO_NB_Q_XSTATS +
+ dev->data->nb_rx_queues * VIRTIO_NB_Q_XSTATS;
+
+ if(n < nstats)
+ return nstats;
+
+ for (i = 0; i < dev->data->nb_rx_queues; i++) {
+ struct virtqueue *rxvq = dev->data->rx_queues[i];
+
+ if(rxvq == NULL)
+ continue;
+
+ 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].value = *(uint64_t *)(((char *)rxvq) +
+ rte_virtio_q_stat_strings[t].offset);
+ count++;
+ }
+ }
+
+ for (i = 0; i < dev->data->nb_tx_queues; i++) {
+ struct virtqueue *txvq = dev->data->tx_queues[i];
+
+ if(txvq == NULL)
+ continue;
+
+ 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].value = *(uint64_t *)(((char *)txvq) +
+ rte_virtio_q_stat_strings[t].offset);
+ count++;
+ }
+ }
+
+ return count;
+}
+
+static void
+virtio_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
+{
+ virtio_update_stats(dev, stats);
+}
+
static void
virtio_dev_stats_reset(struct rte_eth_dev *dev)
{
--
1.9.1
Stephen Hemminger
2015-09-30 17:44:57 UTC
Permalink
On Wed, 30 Sep 2015 10:40:15 +0100
Post by Harry van Haaren
+/* [rt]x_qX_ is prepended to the name string here */
+static const struct rte_virtio_xstats_name_off rte_virtio_q_stat_strings[] = {
+ {"packets", offsetof(struct virtqueue, packets)},
+ {"bytes", offsetof(struct virtqueue, bytes)},
+ {"errors", offsetof(struct virtqueue, errors)},
+}
I don't see the point of this. The point of xstats is to tell the application
about statistics not available through other means.

These stats should be available already in the per queue stats.
Van Haaren, Harry
2015-10-01 08:00:30 UTC
Permalink
+/* [rt]x_qX_ is prepended to the name string here */ static const
+struct rte_virtio_xstats_name_off rte_virtio_q_stat_strings[] = {
+ {"packets", offsetof(struct virtqueue, packets)},
+ {"bytes", offsetof(struct virtqueue, bytes)},
+ {"errors", offsetof(struct virtqueue, errors)}, }
I don't see the point of this. The point of xstats is to tell the application about
statistics not available through other means.
These stats should be available already in the per queue stats.
You're right - these stats are already available in the per-Q stats part of rte_eth_stats.
The virtio implementation of xstats is mostly framework code so we can add other
stats, for example packet size counters, in the near future.

Thanks for reviewing, -Harry
Harry van Haaren
2015-09-30 09:40:16 UTC
Permalink
Add xstats_get() and xstats_reset() functions to igb
driver, and the neccessary strings to expose these
NIC statistics.

Signed-off-by: Harry van Haaren <***@intel.com>
---
drivers/net/e1000/igb_ethdev.c | 137 +++++++++++++++++++++++++++++++++++++++--
1 file changed, 132 insertions(+), 5 deletions(-)

diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index 848ef6e..e99fb69 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -96,7 +96,10 @@ static int eth_igb_link_update(struct rte_eth_dev *dev,
int wait_to_complete);
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 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,
struct rte_eth_dev_info *dev_info);
static void eth_igbvf_infos_get(struct rte_eth_dev *dev,
@@ -292,7 +295,9 @@ static const struct eth_dev_ops eth_igb_ops = {
.allmulticast_disable = eth_igb_allmulticast_disable,
.link_update = eth_igb_link_update,
.stats_get = eth_igb_stats_get,
+ .xstats_get = eth_igb_xstats_get,
.stats_reset = eth_igb_stats_reset,
+ .xstats_reset = eth_igb_xstats_reset,
.dev_infos_get = eth_igb_infos_get,
.mtu_set = eth_igb_mtu_set,
.vlan_filter_set = eth_igb_vlan_filter_set,
@@ -354,6 +359,78 @@ static const struct eth_dev_ops igbvf_eth_dev_ops = {
.get_reg = igbvf_get_regs,
};

+/* store statistics names and its offset in stats structure */
+struct rte_igb_xstats_name_off {
+ char name[RTE_ETH_XSTATS_NAME_SIZE];
+ unsigned offset;
+};
+
+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_errors", offsetof(struct e1000_hw_stats, rxerrc)},
+ {"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)},
+ {"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)},
+ {"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)},
+ {"rx_size_512_to_1023_packets", offsetof(struct e1000_hw_stats,
+ prc1023)},
+ {"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_no_buffer_errors", offsetof(struct e1000_hw_stats, rnbc)},
+ {"rx_undersize_packets", offsetof(struct e1000_hw_stats, ruc)},
+ {"rx_fragment_packets", offsetof(struct e1000_hw_stats, rfc)},
+ {"rx_oversize_packets", offsetof(struct e1000_hw_stats, roc)},
+ {"rx_jabber_packets", 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_bytes", offsetof(struct e1000_hw_stats, tor)},
+ {"tx_total_bytes", offsetof(struct e1000_hw_stats, tot)},
+ {"rx_total_packets", offsetof(struct e1000_hw_stats, tpr)},
+ {"tx_total_packets", offsetof(struct e1000_hw_stats, tpt)},
+ {"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)},
+ {"tx_size_512_to_1023_packets", offsetof(struct e1000_hw_stats,
+ ptc1023)},
+ {"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)},
+};
+
+#define IGB_NB_XSTATS (sizeof(rte_igb_stats_strings) / \
+ sizeof(rte_igb_stats_strings[0]))
+
/**
* Atomically reads the link status information from global
* structure rte_eth_dev.
@@ -1257,11 +1334,8 @@ igb_hardware_init(struct e1000_hw *hw)

/* This function is based on igb_update_stats_counters() in igb/if_igb.c */
static void
-eth_igb_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats)
+igb_read_stats_registers(struct e1000_hw *hw, struct e1000_hw_stats *stats)
{
- struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
- struct e1000_hw_stats *stats =
- E1000_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
int pause_frames;

if(hw->phy.media_type == e1000_media_type_copper ||
@@ -1365,6 +1439,16 @@ eth_igb_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats)
stats->cexterr += E1000_READ_REG(hw, E1000_CEXTERR);
stats->tsctc += E1000_READ_REG(hw, E1000_TSCTC);
stats->tsctfc += E1000_READ_REG(hw, E1000_TSCTFC);
+}
+
+static void
+eth_igb_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats)
+{
+ struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ struct e1000_hw_stats *stats =
+ E1000_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+
+ igb_read_stats_registers(hw, stats);

if (rte_stats == NULL)
return;
@@ -1407,6 +1491,50 @@ eth_igb_stats_reset(struct rte_eth_dev *dev)
}

static void
+eth_igb_xstats_reset(struct rte_eth_dev *dev)
+{
+ struct e1000_hw_stats *stats =
+ E1000_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+
+ /* HW registers are cleared on read */
+ eth_igb_xstats_get(dev, NULL, IGB_NB_XSTATS);
+
+ /* Reset software totals */
+ memset(stats, 0, sizeof(*stats));
+}
+
+static int
+eth_igb_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *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;
+
+ if(n < IGB_NB_XSTATS)
+ return IGB_NB_XSTATS;
+
+ 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++) {
+ snprintf(xstats[i].name, sizeof(xstats[i].name),
+ "%s", rte_igb_stats_strings[i].name);
+ xstats[i].value = *(uint64_t *)(((char *)hw_stats) +
+ rte_igb_stats_strings[i].offset);
+ }
+
+ return IGB_NB_XSTATS;
+}
+
+static void
eth_igbvf_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats)
{
struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
@@ -1461,7 +1589,6 @@ eth_igbvf_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats)
rte_stats->ilbbytes = hw_stats->gorlbc;
rte_stats->olbpackets = hw_stats->gptlbc;
rte_stats->olbbytes = hw_stats->gotlbc;
-
}

static void
--
1.9.1
Harry van Haaren
2015-09-30 09:40:17 UTC
Permalink
Add xstats functionality to igbvf PMD, adding
necessary statistic strings.

Signed-off-by: Harry van Haaren <***@intel.com>
---
drivers/net/e1000/igb_ethdev.c | 62 +++++++++++++++++++++++++++++++++++++-----
1 file changed, 55 insertions(+), 7 deletions(-)

diff --git a/drivers/net/e1000/igb_ethdev.c b/drivers/net/e1000/igb_ethdev.c
index e99fb69..bf762bf 100644
--- a/drivers/net/e1000/igb_ethdev.c
+++ b/drivers/net/e1000/igb_ethdev.c
@@ -152,7 +152,10 @@ static int igbvf_dev_start(struct rte_eth_dev *dev);
static void igbvf_dev_stop(struct rte_eth_dev *dev);
static void igbvf_dev_close(struct rte_eth_dev *dev);
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 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 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);
@@ -346,7 +349,9 @@ static const struct eth_dev_ops igbvf_eth_dev_ops = {
.dev_close = igbvf_dev_close,
.link_update = eth_igb_link_update,
.stats_get = eth_igbvf_stats_get,
+ .xstats_get = eth_igbvf_xstats_get,
.stats_reset = eth_igbvf_stats_reset,
+ .xstats_reset = eth_igbvf_stats_reset,
.vlan_filter_set = igbvf_vlan_filter_set,
.dev_infos_get = eth_igbvf_infos_get,
.rx_queue_setup = eth_igb_rx_queue_setup,
@@ -431,6 +436,17 @@ static const struct rte_igb_xstats_name_off rte_igb_stats_strings[] = {
#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)},
+};
+
+#define IGBVF_NB_XSTATS (sizeof(rte_igbvf_stats_strings) / \
+ sizeof(rte_igbvf_stats_strings[0]))
+
/**
* Atomically reads the link status information from global
* structure rte_eth_dev.
@@ -1535,12 +1551,8 @@ eth_igb_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
}

static void
-eth_igbvf_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats)
+igbvf_read_stats_registers(struct e1000_hw *hw, struct e1000_vf_stats *hw_stats)
{
- struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
- struct e1000_vf_stats *hw_stats = (struct e1000_vf_stats*)
- E1000_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
-
/* Good Rx packets, include VF loopback */
UPDATE_VF_STAT(E1000_VFGPRC,
hw_stats->last_gprc, hw_stats->gprc);
@@ -1576,6 +1588,43 @@ eth_igbvf_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats)
/* Good Tx loopback octets */
UPDATE_VF_STAT(E1000_VFGOTLBC,
hw_stats->last_gotlbc, hw_stats->gotlbc);
+}
+
+static int
+eth_igbvf_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
+ unsigned n)
+{
+ struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ struct e1000_vf_stats *hw_stats = (struct e1000_vf_stats *)
+ E1000_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+ unsigned i;
+
+ if(n < IGBVF_NB_XSTATS)
+ return IGBVF_NB_XSTATS;
+
+ igbvf_read_stats_registers(hw, hw_stats);
+
+ if(!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].value = *(uint64_t *)(((char *)hw_stats) +
+ rte_igbvf_stats_strings[i].offset);
+ }
+
+ return IGBVF_NB_XSTATS;
+}
+
+static void
+eth_igbvf_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *rte_stats)
+{
+ struct e1000_hw *hw = E1000_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ struct e1000_vf_stats *hw_stats = (struct e1000_vf_stats *)
+ E1000_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+
+ igbvf_read_stats_registers(hw, hw_stats);

if (rte_stats == NULL)
return;
@@ -1603,7 +1652,6 @@ eth_igbvf_stats_reset(struct rte_eth_dev *dev)
/* reset HW current stats*/
memset(&hw_stats->gprc, 0, sizeof(*hw_stats) -
offsetof(struct e1000_vf_stats, gprc));
-
}

static void
--
1.9.1
Harry van Haaren
2015-09-30 09:40:18 UTC
Permalink
Updated and add statistic strings as used by xstats_get().

Signed-off-by: Harry van Haaren <***@intel.com>
---
drivers/net/ixgbe/ixgbe_ethdev.c | 295 ++++++++++++++++++++++++++++++++++++---
1 file changed, 273 insertions(+), 22 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index ec2918c..4fb7313 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -506,29 +506,280 @@ struct rte_ixgbe_xstats_name_off {
};

static const struct rte_ixgbe_xstats_name_off rte_ixgbe_stats_strings[] = {
- {"rx_illegal_byte_err", offsetof(struct ixgbe_hw_stats, errbc)},
- {"rx_len_err", offsetof(struct ixgbe_hw_stats, rlec)},
- {"rx_undersize_count", offsetof(struct ixgbe_hw_stats, ruc)},
- {"rx_oversize_count", offsetof(struct ixgbe_hw_stats, roc)},
- {"rx_fragment_count", offsetof(struct ixgbe_hw_stats, rfc)},
- {"rx_jabber_count", offsetof(struct ixgbe_hw_stats, rjc)},
- {"l3_l4_xsum_error", offsetof(struct ixgbe_hw_stats, xec)},
- {"mac_local_fault", offsetof(struct ixgbe_hw_stats, mlfc)},
- {"mac_remote_fault", offsetof(struct ixgbe_hw_stats, mrfc)},
- {"mac_short_pkt_discard", offsetof(struct ixgbe_hw_stats, mspdc)},
- {"fccrc_error", offsetof(struct ixgbe_hw_stats, fccrc)},
- {"fcoe_drop", offsetof(struct ixgbe_hw_stats, fcoerpdc)},
- {"fc_last_error", offsetof(struct ixgbe_hw_stats, fclast)},
- {"rx_broadcast_packets", offsetof(struct ixgbe_hw_stats, bprc)},
- {"rx_phy_multicast_packets", offsetof(struct ixgbe_hw_stats, mprc)},
- {"mgmt_pkts_dropped", offsetof(struct ixgbe_hw_stats, mngpdc)},
{"rx_crc_errors", offsetof(struct ixgbe_hw_stats, crcerrs)},
- {"fdir_match", offsetof(struct ixgbe_hw_stats, fdirmatch)},
- {"fdir_miss", offsetof(struct ixgbe_hw_stats, fdirmiss)},
- {"tx_flow_control_xon", offsetof(struct ixgbe_hw_stats, lxontxc)},
- {"rx_flow_control_xon", offsetof(struct ixgbe_hw_stats, lxonrxc)},
- {"tx_flow_control_xoff", offsetof(struct ixgbe_hw_stats, lxofftxc)},
- {"rx_flow_control_xoff", offsetof(struct ixgbe_hw_stats, lxoffrxc)},
+ {"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_size_512_to_1023_packets", offsetof(struct ixgbe_hw_stats,
+ prc1023)},
+ {"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_managment_packets", offsetof(struct ixgbe_hw_stats, mngprc)},
+ {"rx_managment_dropped", offsetof(struct ixgbe_hw_stats, mngpdc)},
+ {"tx_managment_packets", offsetof(struct ixgbe_hw_stats, mngptc)},
+ {"rx_total_bytes", offsetof(struct ixgbe_hw_stats, tor)},
+ {"rx_total_packets", offsetof(struct ixgbe_hw_stats, tpr)},
+ {"tx_total_bytes", 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)},
+ {"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_discard", offsetof(struct ixgbe_hw_stats, mspdc)},
+ {"rx_l3_l4_xsum_error", offsetof(struct ixgbe_hw_stats, xec)},
+
+ {"flow_director_added_filters", offsetof(struct ixgbe_hw_stats,
+ fdirustat_add)},
+ {"flow_director_removed_filters", offsetof(struct ixgbe_hw_stats,
+ fdirustat_remove)},
+ {"flow_director_filter_add_errors", offsetof(struct ixgbe_hw_stats,
+ fdirfstat_fadd)},
+ {"flow_director_filter_remove_errors", offsetof(struct ixgbe_hw_stats,
+ fdirfstat_fremove)},
+ {"flow_director_matched_filters", offsetof(struct ixgbe_hw_stats,
+ fdirmatch)},
+ {"flow_director_missed_filters", offsetof(struct ixgbe_hw_stats,
+ fdirmiss)},
+
+ {"rx_fcoe_crc_errors", offsetof(struct ixgbe_hw_stats, fccrc)},
+ {"rx_fcoe_dropped", offsetof(struct ixgbe_hw_stats, fcoerpdc)},
+ {"rx_fcoe_no_mbufs_avail_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)},
+ {"rx_fcoe_no_direct_data_placement", offsetof(struct ixgbe_hw_stats,
+ fcoe_noddp)},
+ {"rx_fcoe_no_direct_data_placement_ext_buff",
+ offsetof(struct ixgbe_hw_stats, fcoe_noddp_ext_buff)},
+
+ {"tx_flow_control_xon_packets", offsetof(struct ixgbe_hw_stats,
+ lxontxc)},
+ {"rx_flow_control_xon_packets", offsetof(struct ixgbe_hw_stats,
+ lxonrxc)},
+ {"tx_flow_control_xoff_packets", offsetof(struct ixgbe_hw_stats,
+ lxofftxc)},
+ {"rx_flow_control_xoff_packets", offsetof(struct ixgbe_hw_stats,
+ lxoffrxc)},
+ {"rx_total_missed_packets", offsetof(struct ixgbe_hw_stats, mpctotal)},
+
+ {"rx_q0_missed_packets", offsetof(struct ixgbe_hw_stats, mpc[0])},
+ {"rx_q1_missed_packets", offsetof(struct ixgbe_hw_stats, mpc[1])},
+ {"rx_q2_missed_packets", offsetof(struct ixgbe_hw_stats, mpc[2])},
+ {"rx_q3_missed_packets", offsetof(struct ixgbe_hw_stats, mpc[3])},
+ {"rx_q4_missed_packets", offsetof(struct ixgbe_hw_stats, mpc[4])},
+ {"rx_q5_missed_packets", offsetof(struct ixgbe_hw_stats, mpc[5])},
+ {"rx_q6_missed_packets", offsetof(struct ixgbe_hw_stats, mpc[6])},
+ {"rx_q7_missed_packets", offsetof(struct ixgbe_hw_stats, mpc[7])},
+
+ {"rx_q0_no_mbufs_avail_errors", offsetof(struct ixgbe_hw_stats,
+ rnbc[0])},
+ {"rx_q1_no_mbufs_avail_errors", offsetof(struct ixgbe_hw_stats,
+ rnbc[1])},
+ {"rx_q2_no_mbufs_avail_errors", offsetof(struct ixgbe_hw_stats,
+ rnbc[2])},
+ {"rx_q3_no_mbufs_avail_errors", offsetof(struct ixgbe_hw_stats,
+ rnbc[3])},
+ {"rx_q4_no_mbufs_avail_errors", offsetof(struct ixgbe_hw_stats,
+ rnbc[4])},
+ {"rx_q5_no_mbufs_avail_errors", offsetof(struct ixgbe_hw_stats,
+ rnbc[5])},
+ {"rx_q6_no_mbufs_avail_errors", offsetof(struct ixgbe_hw_stats,
+ rnbc[6])},
+ {"rx_q7_no_mbufs_avail_errors", offsetof(struct ixgbe_hw_stats,
+ rnbc[7])},
+
+ {"tx_q0_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxontxc[0])},
+ {"tx_q1_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxontxc[1])},
+ {"tx_q2_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxontxc[2])},
+ {"tx_q3_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxontxc[3])},
+ {"tx_q4_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxontxc[4])},
+ {"tx_q5_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxontxc[5])},
+ {"tx_q6_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxontxc[6])},
+ {"tx_q7_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxontxc[7])},
+
+ {"rx_q0_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxonrxc[0])},
+ {"rx_q1_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxonrxc[1])},
+ {"rx_q2_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxonrxc[2])},
+ {"rx_q3_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxonrxc[3])},
+ {"rx_q4_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxonrxc[4])},
+ {"rx_q5_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxonrxc[5])},
+ {"rx_q6_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxonrxc[6])},
+ {"rx_q7_xon_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxonrxc[7])},
+
+ {"tx_q0_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxofftxc[0])},
+ {"tx_q1_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxofftxc[1])},
+ {"tx_q2_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxofftxc[2])},
+ {"tx_q3_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxofftxc[3])},
+ {"tx_q4_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxofftxc[4])},
+ {"tx_q5_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxofftxc[5])},
+ {"tx_q6_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxofftxc[6])},
+ {"tx_q7_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxofftxc[7])},
+
+ {"rx_q0_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxoffrxc[0])},
+ {"rx_q1_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxoffrxc[1])},
+ {"rx_q2_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxoffrxc[2])},
+ {"rx_q3_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxoffrxc[3])},
+ {"rx_q4_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxoffrxc[4])},
+ {"rx_q5_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxoffrxc[5])},
+ {"rx_q6_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxoffrxc[6])},
+ {"rx_q7_xoff_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxoffrxc[7])},
+
+ {"xx_q0_xon_to_off_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxon2offc[0])},
+ {"xx_q1_xon_to_off_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxon2offc[1])},
+ {"xx_q2_xon_to_off_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxon2offc[2])},
+ {"xx_q3_xon_to_off_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxon2offc[3])},
+ {"xx_q4_xon_to_off_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxon2offc[4])},
+ {"xx_q5_xon_to_off_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxon2offc[5])},
+ {"xx_q6_xon_to_off_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxon2offc[6])},
+ {"xx_q7_xon_to_off_priority_packets", offsetof(struct ixgbe_hw_stats,
+ pxon2offc[7])},
+
+ {"rx_q0_packets", offsetof(struct ixgbe_hw_stats, qprc[0])},
+ {"rx_q1_packets", offsetof(struct ixgbe_hw_stats, qprc[1])},
+ {"rx_q2_packets", offsetof(struct ixgbe_hw_stats, qprc[2])},
+ {"rx_q3_packets", offsetof(struct ixgbe_hw_stats, qprc[3])},
+ {"rx_q4_packets", offsetof(struct ixgbe_hw_stats, qprc[4])},
+ {"rx_q5_packets", offsetof(struct ixgbe_hw_stats, qprc[5])},
+ {"rx_q6_packets", offsetof(struct ixgbe_hw_stats, qprc[6])},
+ {"rx_q7_packets", offsetof(struct ixgbe_hw_stats, qprc[7])},
+ {"rx_q8_packets", offsetof(struct ixgbe_hw_stats, qprc[8])},
+ {"rx_q9_packets", offsetof(struct ixgbe_hw_stats, qprc[9])},
+ {"rx_q10_packets", offsetof(struct ixgbe_hw_stats, qprc[10])},
+ {"rx_q11_packets", offsetof(struct ixgbe_hw_stats, qprc[11])},
+ {"rx_q12_packets", offsetof(struct ixgbe_hw_stats, qprc[12])},
+ {"rx_q13_packets", offsetof(struct ixgbe_hw_stats, qprc[13])},
+ {"rx_q14_packets", offsetof(struct ixgbe_hw_stats, qprc[14])},
+ {"rx_q15_packets", offsetof(struct ixgbe_hw_stats, qprc[15])},
+
+ {"tx_q0_packets", offsetof(struct ixgbe_hw_stats, qptc[0])},
+ {"tx_q1_packets", offsetof(struct ixgbe_hw_stats, qptc[1])},
+ {"tx_q2_packets", offsetof(struct ixgbe_hw_stats, qptc[2])},
+ {"tx_q3_packets", offsetof(struct ixgbe_hw_stats, qptc[3])},
+ {"tx_q4_packets", offsetof(struct ixgbe_hw_stats, qptc[4])},
+ {"tx_q5_packets", offsetof(struct ixgbe_hw_stats, qptc[5])},
+ {"tx_q6_packets", offsetof(struct ixgbe_hw_stats, qptc[6])},
+ {"tx_q7_packets", offsetof(struct ixgbe_hw_stats, qptc[7])},
+ {"tx_q8_packets", offsetof(struct ixgbe_hw_stats, qptc[8])},
+ {"tx_q9_packets", offsetof(struct ixgbe_hw_stats, qptc[9])},
+ {"tx_q10_packets", offsetof(struct ixgbe_hw_stats, qptc[10])},
+ {"tx_q11_packets", offsetof(struct ixgbe_hw_stats, qptc[11])},
+ {"tx_q12_packets", offsetof(struct ixgbe_hw_stats, qptc[12])},
+ {"tx_q13_packets", offsetof(struct ixgbe_hw_stats, qptc[13])},
+ {"tx_q14_packets", offsetof(struct ixgbe_hw_stats, qptc[14])},
+ {"tx_q15_packets", offsetof(struct ixgbe_hw_stats, qptc[15])},
+
+ {"rx_q0_bytes", offsetof(struct ixgbe_hw_stats, qbrc[0])},
+ {"rx_q1_bytes", offsetof(struct ixgbe_hw_stats, qbrc[1])},
+ {"rx_q2_bytes", offsetof(struct ixgbe_hw_stats, qbrc[2])},
+ {"rx_q3_bytes", offsetof(struct ixgbe_hw_stats, qbrc[3])},
+ {"rx_q4_bytes", offsetof(struct ixgbe_hw_stats, qbrc[4])},
+ {"rx_q5_bytes", offsetof(struct ixgbe_hw_stats, qbrc[5])},
+ {"rx_q6_bytes", offsetof(struct ixgbe_hw_stats, qbrc[6])},
+ {"rx_q7_bytes", offsetof(struct ixgbe_hw_stats, qbrc[7])},
+ {"rx_q8_bytes", offsetof(struct ixgbe_hw_stats, qbrc[8])},
+ {"rx_q9_bytes", offsetof(struct ixgbe_hw_stats, qbrc[9])},
+ {"rx_q10_bytes", offsetof(struct ixgbe_hw_stats, qbrc[10])},
+ {"rx_q11_bytes", offsetof(struct ixgbe_hw_stats, qbrc[11])},
+ {"rx_q12_bytes", offsetof(struct ixgbe_hw_stats, qbrc[12])},
+ {"rx_q13_bytes", offsetof(struct ixgbe_hw_stats, qbrc[13])},
+ {"rx_q14_bytes", offsetof(struct ixgbe_hw_stats, qbrc[14])},
+ {"rx_q15_bytes", offsetof(struct ixgbe_hw_stats, qbrc[15])},
+
+ {"tx_q0_bytes", offsetof(struct ixgbe_hw_stats, qbtc[0])},
+ {"tx_q1_bytes", offsetof(struct ixgbe_hw_stats, qbtc[1])},
+ {"tx_q2_bytes", offsetof(struct ixgbe_hw_stats, qbtc[2])},
+ {"tx_q3_bytes", offsetof(struct ixgbe_hw_stats, qbtc[3])},
+ {"tx_q4_bytes", offsetof(struct ixgbe_hw_stats, qbtc[4])},
+ {"tx_q5_bytes", offsetof(struct ixgbe_hw_stats, qbtc[5])},
+ {"tx_q6_bytes", offsetof(struct ixgbe_hw_stats, qbtc[6])},
+ {"tx_q7_bytes", offsetof(struct ixgbe_hw_stats, qbtc[7])},
+ {"tx_q8_bytes", offsetof(struct ixgbe_hw_stats, qbtc[8])},
+ {"tx_q9_bytes", offsetof(struct ixgbe_hw_stats, qbtc[9])},
+ {"tx_q10_bytes", offsetof(struct ixgbe_hw_stats, qbtc[10])},
+ {"tx_q11_bytes", offsetof(struct ixgbe_hw_stats, qbtc[11])},
+ {"tx_q12_bytes", offsetof(struct ixgbe_hw_stats, qbtc[12])},
+ {"tx_q13_bytes", offsetof(struct ixgbe_hw_stats, qbtc[13])},
+ {"tx_q14_bytes", offsetof(struct ixgbe_hw_stats, qbtc[14])},
+ {"tx_q15_bytes", offsetof(struct ixgbe_hw_stats, qbtc[15])},
+
+ {"rx_q0_dropped", offsetof(struct ixgbe_hw_stats, qprdc[0])},
+ {"rx_q1_dropped", offsetof(struct ixgbe_hw_stats, qprdc[1])},
+ {"rx_q2_dropped", offsetof(struct ixgbe_hw_stats, qprdc[2])},
+ {"rx_q3_dropped", offsetof(struct ixgbe_hw_stats, qprdc[3])},
+ {"rx_q4_dropped", offsetof(struct ixgbe_hw_stats, qprdc[4])},
+ {"rx_q5_dropped", offsetof(struct ixgbe_hw_stats, qprdc[5])},
+ {"rx_q6_dropped", offsetof(struct ixgbe_hw_stats, qprdc[6])},
+ {"rx_q7_dropped", offsetof(struct ixgbe_hw_stats, qprdc[7])},
+ {"rx_q8_dropped", offsetof(struct ixgbe_hw_stats, qprdc[8])},
+ {"rx_q9_dropped", offsetof(struct ixgbe_hw_stats, qprdc[9])},
+ {"rx_q10_dropped", offsetof(struct ixgbe_hw_stats, qprdc[10])},
+ {"rx_q11_dropped", offsetof(struct ixgbe_hw_stats, qprdc[11])},
+ {"rx_q12_dropped", offsetof(struct ixgbe_hw_stats, qprdc[12])},
+ {"rx_q13_dropped", offsetof(struct ixgbe_hw_stats, qprdc[13])},
+ {"rx_q14_dropped", offsetof(struct ixgbe_hw_stats, qprdc[14])},
+ {"rx_q15_dropped", offsetof(struct ixgbe_hw_stats, qprdc[15])},
};

#define IXGBE_NB_XSTATS (sizeof(rte_ixgbe_stats_strings) / \
--
1.9.1
Harry van Haaren
2015-09-30 09:40:19 UTC
Permalink
Add xstats() functions and stat strings as necessary to ixgbevf PMD.

Signed-off-by: Harry van Haaren <***@intel.com>
---
drivers/net/ixgbe/ixgbe_ethdev.c | 51 ++++++++++++++++++++++++++++++++++++++--
1 file changed, 49 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ixgbe/ixgbe_ethdev.c b/drivers/net/ixgbe/ixgbe_ethdev.c
index 4fb7313..1518cc1 100644
--- a/drivers/net/ixgbe/ixgbe_ethdev.c
+++ b/drivers/net/ixgbe/ixgbe_ethdev.c
@@ -149,6 +149,8 @@ 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);
+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_queue_stats_mapping_set(struct rte_eth_dev *eth_dev,
@@ -477,7 +479,9 @@ static const struct eth_dev_ops ixgbevf_eth_dev_ops = {
.dev_stop = ixgbevf_dev_stop,
.link_update = ixgbe_dev_link_update,
.stats_get = ixgbevf_dev_stats_get,
+ .xstats_get = ixgbevf_dev_xstats_get,
.stats_reset = ixgbevf_dev_stats_reset,
+ .xstats_reset = ixgbevf_dev_stats_reset,
.dev_close = ixgbevf_dev_close,
.dev_infos_get = ixgbevf_dev_info_get,
.mtu_set = ixgbevf_dev_set_mtu,
@@ -785,6 +789,13 @@ static const struct rte_ixgbe_xstats_name_off rte_ixgbe_stats_strings[] = {
#define IXGBE_NB_XSTATS (sizeof(rte_ixgbe_stats_strings) / \
sizeof(rte_ixgbe_stats_strings[0]))

+static const struct rte_ixgbe_xstats_name_off rte_ixgbevf_stats_strings[] = {
+ {"rx_multicast_packets", offsetof(struct ixgbevf_hw_stats, vfmprc)},
+};
+
+#define IXGBEVF_NB_XSTATS (sizeof(rte_ixgbevf_stats_strings) / \
+ sizeof(rte_ixgbevf_stats_strings[0]))
+
/**
* Atomically reads the link status information from global
* structure rte_eth_dev.
@@ -2531,7 +2542,7 @@ ixgbe_dev_xstats_reset(struct rte_eth_dev *dev)
}

static void
-ixgbevf_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
+ixgbevf_update_stats(struct rte_eth_dev *dev)
{
struct ixgbe_hw *hw = IXGBE_DEV_PRIVATE_TO_HW(dev->data->dev_private);
struct ixgbevf_hw_stats *hw_stats = (struct ixgbevf_hw_stats*)
@@ -2556,8 +2567,44 @@ ixgbevf_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
/* Rx Multicst Packet */
UPDATE_VF_STAT(IXGBE_VFMPRC,
hw_stats->last_vfmprc, hw_stats->vfmprc);
+}

- if (stats == NULL)
+static int
+ixgbevf_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
+ unsigned n)
+{
+ struct ixgbevf_hw_stats *hw_stats = (struct ixgbevf_hw_stats *)
+ IXGBE_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+ unsigned i;
+
+ if(n < IXGBEVF_NB_XSTATS)
+ return IXGBEVF_NB_XSTATS;
+
+ ixgbevf_update_stats(dev);
+
+ if (!xstats)
+ return 0;
+
+ /* 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].value = *(uint64_t *)(((char *)hw_stats) +
+ rte_ixgbevf_stats_strings[i].offset);
+ }
+
+ return IXGBEVF_NB_XSTATS;
+}
+
+static void
+ixgbevf_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
+{
+ struct ixgbevf_hw_stats *hw_stats = (struct ixgbevf_hw_stats *)
+ IXGBE_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+
+ ixgbevf_update_stats(dev);
+
+ if(stats == NULL)
return;

stats->ipackets = hw_stats->vfgprc;
--
1.9.1
Harry van Haaren
2015-09-30 09:40:20 UTC
Permalink
Add xstats functions to i40e PMD, allowing extended statistics
to be retrieved from the NIC and exposed to the DPDK.

Signed-off-by: Harry van Haaren <***@intel.com>
---
drivers/net/i40e/i40e_ethdev.c | 268 +++++++++++++++++++++++++++++++++++++++--
1 file changed, 261 insertions(+), 7 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c
index 2dd9fdc..f2952b9 100644
--- a/drivers/net/i40e/i40e_ethdev.c
+++ b/drivers/net/i40e/i40e_ethdev.c
@@ -127,7 +127,10 @@ static int i40e_dev_set_link_up(struct rte_eth_dev *dev);
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);
static void i40e_dev_stats_reset(struct rte_eth_dev *dev);
+static void i40e_dev_xstats_reset(struct rte_eth_dev *dev);
static int i40e_dev_queue_stats_mapping_set(struct rte_eth_dev *dev,
uint16_t queue_id,
uint8_t stat_idx,
@@ -232,6 +235,8 @@ static int i40e_timesync_read_rx_timestamp(struct rte_eth_dev *dev,
uint32_t flags);
static int i40e_timesync_read_tx_timestamp(struct rte_eth_dev *dev,
struct timespec *timestamp);
+static void i40e_read_stats_registers(struct i40e_pf *pf, struct i40e_hw *hw);
+

static const struct rte_pci_id pci_id_i40e_map[] = {
#define RTE_PCI_DEV_ID_DECL_I40E(vend, dev) {RTE_PCI_DEVICE(vend, dev)},
@@ -252,7 +257,9 @@ static const struct eth_dev_ops i40e_eth_dev_ops = {
.dev_set_link_down = i40e_dev_set_link_down,
.link_update = i40e_dev_link_update,
.stats_get = i40e_dev_stats_get,
+ .xstats_get = i40e_dev_xstats_get,
.stats_reset = i40e_dev_stats_reset,
+ .xstats_reset = i40e_dev_xstats_reset,
.queue_stats_mapping_set = i40e_dev_queue_stats_mapping_set,
.dev_infos_get = i40e_dev_info_get,
.vlan_filter_set = i40e_vlan_filter_set,
@@ -291,6 +298,190 @@ static const struct eth_dev_ops i40e_eth_dev_ops = {
.timesync_read_tx_timestamp = i40e_timesync_read_tx_timestamp,
};

+/* store statistics names and its offset in stats structure */
+struct rte_i40e_xstats_name_off {
+ char name[RTE_ETH_XSTATS_NAME_SIZE];
+ unsigned offset;
+};
+
+static const struct rte_i40e_xstats_name_off rte_i40e_stats_strings[] = {
+ {"rx_bytes", offsetof(struct i40e_eth_stats, rx_bytes)},
+ {"rx_unicast_packets", offsetof(struct i40e_eth_stats, rx_unicast)},
+ {"rx_multicast_packets", offsetof(struct i40e_eth_stats, rx_multicast)},
+ {"rx_broadcast_packets", offsetof(struct i40e_eth_stats, rx_broadcast)},
+ {"rx_dropped", offsetof(struct i40e_eth_stats, rx_discards)},
+ {"rx_unknown_protocol_packets", offsetof(struct i40e_eth_stats,
+ rx_unknown_protocol)},
+ {"tx_bytes", offsetof(struct i40e_eth_stats, tx_bytes)},
+ {"tx_unicast_packets", offsetof(struct i40e_eth_stats, tx_unicast)},
+ {"tx_multicast_packets", offsetof(struct i40e_eth_stats, tx_multicast)},
+ {"tx_broadcast_packets", offsetof(struct i40e_eth_stats, tx_broadcast)},
+ {"tx_dropped", offsetof(struct i40e_eth_stats, tx_discards)},
+ {"tx_errors", offsetof(struct i40e_eth_stats, tx_errors)},
+};
+
+static const struct rte_i40e_xstats_name_off rte_i40e_hw_port_strings[] = {
+ {"tx_link_down_dropped", offsetof(struct i40e_hw_port_stats,
+ tx_dropped_link_down)},
+ {"rx_crc_errors", offsetof(struct i40e_hw_port_stats, crc_errors)},
+ {"rx_illegal_bytes", offsetof(struct i40e_hw_port_stats,
+ illegal_bytes)},
+ {"rx_error_bytes", offsetof(struct i40e_hw_port_stats, error_bytes)},
+ {"mac_local_errors", offsetof(struct i40e_hw_port_stats,
+ mac_local_faults)},
+ {"mac_remote_errors", offsetof(struct i40e_hw_port_stats,
+ mac_remote_faults)},
+ {"rx_length_errors", offsetof(struct i40e_hw_port_stats,
+ rx_length_errors)},
+ {"tx_xon_packets", offsetof(struct i40e_hw_port_stats, link_xon_tx)},
+ {"rx_xon_packets", offsetof(struct i40e_hw_port_stats, link_xon_rx)},
+ {"tx_xoff_packets", offsetof(struct i40e_hw_port_stats, link_xoff_tx)},
+ {"rx_xoff_packets", offsetof(struct i40e_hw_port_stats, link_xoff_rx)},
+ {"rx_size_64_packets", offsetof(struct i40e_hw_port_stats, rx_size_64)},
+ {"rx_size_65_to_127_packets", offsetof(struct i40e_hw_port_stats,
+ rx_size_127)},
+ {"rx_size_128_to_255_packets", offsetof(struct i40e_hw_port_stats,
+ rx_size_255)},
+ {"rx_size_256_to_511_packets", offsetof(struct i40e_hw_port_stats,
+ rx_size_511)},
+ {"rx_size_512_to_1023_packets", offsetof(struct i40e_hw_port_stats,
+ rx_size_1023)},
+ {"rx_size_1024_to_1522_packets", offsetof(struct i40e_hw_port_stats,
+ rx_size_1522)},
+ {"rx_size_1523_to_max_packets", offsetof(struct i40e_hw_port_stats,
+ rx_size_big)},
+ {"rx_undersized_packets", offsetof(struct i40e_hw_port_stats,
+ rx_undersize)},
+ {"rx_oversize_packets", offsetof(struct i40e_hw_port_stats,
+ rx_oversize)},
+ {"rx_mac_short_dropped", offsetof(struct i40e_hw_port_stats,
+ mac_short_packet_dropped)},
+ {"rx_fragmented_packets", offsetof(struct i40e_hw_port_stats,
+ rx_fragments)},
+ {"rx_jabber_packets", offsetof(struct i40e_hw_port_stats, rx_jabber)},
+ {"tx_size_64_packets", offsetof(struct i40e_hw_port_stats, tx_size_64)},
+ {"tx_size_65_to_127_packets", offsetof(struct i40e_hw_port_stats,
+ tx_size_127)},
+ {"tx_size_128_to_255_packets", offsetof(struct i40e_hw_port_stats,
+ tx_size_255)},
+ {"tx_size_256_to_511_packets", offsetof(struct i40e_hw_port_stats,
+ tx_size_511)},
+ {"tx_size_512_to_1023_packets", offsetof(struct i40e_hw_port_stats,
+ tx_size_1023)},
+ {"tx_size_1024_to_1522_packets", offsetof(struct i40e_hw_port_stats,
+ tx_size_1522)},
+ {"tx_size_1523_to_max_packets", offsetof(struct i40e_hw_port_stats,
+ tx_size_big)},
+ {"rx_flow_director_atr_match_packets",
+ offsetof(struct i40e_hw_port_stats, fd_atr_match)},
+ {"rx_flow_director_sb_match_packets",
+ offsetof(struct i40e_hw_port_stats, fd_sb_match)},
+ {"tx_low_power_idle_status", offsetof(struct i40e_hw_port_stats,
+ tx_lpi_status)},
+ {"rx_low_power_idle_status", offsetof(struct i40e_hw_port_stats,
+ rx_lpi_status)},
+ {"tx_low_power_idle_count", offsetof(struct i40e_hw_port_stats,
+ tx_lpi_count)},
+ {"rx_low_power_idle_count", offsetof(struct i40e_hw_port_stats,
+ rx_lpi_count)},
+
+ /* priority_xon_rx[8] */
+ {"tx_q0_xon_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xon_tx[0])},
+ {"tx_q1_xon_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xon_tx[1])},
+ {"tx_q2_xon_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xon_tx[2])},
+ {"tx_q3_xon_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xon_tx[3])},
+ {"tx_q4_xon_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xon_tx[4])},
+ {"tx_q5_xon_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xon_tx[5])},
+ {"tx_q6_xon_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xon_tx[6])},
+ {"tx_q7_xon_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xon_tx[7])},
+
+ /* priority_xon_rx[8] */
+ {"rx_q0_xon_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xon_rx[0])},
+ {"rx_q1_xon_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xon_rx[1])},
+ {"rx_q2_xon_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xon_rx[2])},
+ {"rx_q3_xon_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xon_rx[3])},
+ {"rx_q4_xon_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xon_rx[4])},
+ {"rx_q5_xon_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xon_rx[5])},
+ {"rx_q6_xon_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xon_rx[6])},
+ {"rx_q7_xon_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xon_rx[7])},
+
+ /* priority_xoff_tx[8] */
+ {"tx_q0_xoff_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xoff_tx[0])},
+ {"tx_q1_xoff_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xoff_tx[1])},
+ {"tx_q2_xoff_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xoff_tx[2])},
+ {"tx_q3_xoff_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xoff_tx[3])},
+ {"tx_q4_xoff_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xoff_tx[4])},
+ {"tx_q5_xoff_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xoff_tx[5])},
+ {"tx_q6_xoff_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xoff_tx[6])},
+ {"tx_q7_xoff_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xoff_tx[7])},
+
+ /* priority_xoff_rx[8] */
+ {"rx_q0_xoff_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xoff_rx[0])},
+ {"rx_q1_xoff_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xoff_rx[1])},
+ {"rx_q2_xoff_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xoff_rx[2])},
+ {"rx_q3_xoff_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xoff_rx[3])},
+ {"rx_q4_xoff_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xoff_rx[4])},
+ {"rx_q5_xoff_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xoff_rx[5])},
+ {"rx_q6_xoff_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xoff_rx[6])},
+ {"rx_q7_xoff_priority_packets", offsetof(struct i40e_hw_port_stats,
+ priority_xoff_rx[7])},
+
+ /* priority_xon_2_xoff[8] */
+ {"xx_q0_xon_to_xoff_priority_packets",
+ offsetof(struct i40e_hw_port_stats, priority_xon_2_xoff[0])},
+ {"xx_q1_xon_to_xoff_priority_packets",
+ offsetof(struct i40e_hw_port_stats, priority_xon_2_xoff[1])},
+ {"xx_q2_xon_to_xoff_priority_packets",
+ offsetof(struct i40e_hw_port_stats, priority_xon_2_xoff[2])},
+ {"xx_q3_xon_to_xoff_priority_packets",
+ offsetof(struct i40e_hw_port_stats, priority_xon_2_xoff[3])},
+ {"xx_q4_xon_to_xoff_priority_packets",
+ offsetof(struct i40e_hw_port_stats, priority_xon_2_xoff[4])},
+ {"xx_q5_xon_to_xoff_priority_packets",
+ offsetof(struct i40e_hw_port_stats, priority_xon_2_xoff[5])},
+ {"xx_q6_xon_to_xoff_priority_packets",
+ offsetof(struct i40e_hw_port_stats, priority_xon_2_xoff[6])},
+ {"xx_q7_xon_to_xoff_priority_packets",
+ offsetof(struct i40e_hw_port_stats, priority_xon_2_xoff[7])},
+};
+
+#define I40E_NB_ETH_XSTATS (sizeof(rte_i40e_stats_strings) / \
+ sizeof(rte_i40e_stats_strings[0]))
+#define I40E_NB_HW_PORT_XSTATS (sizeof(rte_i40e_hw_port_strings) / \
+ sizeof(rte_i40e_hw_port_strings[0]))
+#define I40E_NB_XSTATS (I40E_NB_ETH_XSTATS + I40E_NB_HW_PORT_XSTATS)
+
static struct eth_driver rte_i40e_pmd = {
.pci_drv = {
.name = "rte_i40e_pmd",
@@ -1322,16 +1513,12 @@ i40e_update_vsi_stats(struct i40e_vsi *vsi)
vsi->vsi_id);
}

-/* Get all statistics of a port */
static void
-i40e_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
+i40e_read_stats_registers(struct i40e_pf *pf, struct i40e_hw *hw)
{
- uint32_t i;
- struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
- struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ unsigned int i;
struct i40e_hw_port_stats *ns = &pf->stats; /* new stats */
struct i40e_hw_port_stats *os = &pf->stats_offset; /* old stats */
-
/* Get statistics of struct i40e_eth_stats */
i40e_stat_update_48(hw, I40E_GLPRT_GORCH(hw->port),
I40E_GLPRT_GORCL(hw->port),
@@ -1508,8 +1695,21 @@ i40e_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)

pf->offset_loaded = true;

- if (pf->main_vsi)
+ if(pf->main_vsi)
i40e_update_vsi_stats(pf->main_vsi);
+}
+
+/* Get all statistics of a port */
+static void
+i40e_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
+{
+ struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ struct i40e_hw_port_stats *ns = &pf->stats; /* new stats */
+ unsigned i;
+
+ /* call read registers - updates values, now write them to struct */
+ i40e_read_stats_registers(pf, hw);

stats->ipackets = ns->eth.rx_unicast + ns->eth.rx_multicast +
ns->eth.rx_broadcast;
@@ -1599,6 +1799,60 @@ i40e_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
PMD_DRV_LOG(DEBUG, "***************** PF stats end ********************");
}

+static void
+i40e_dev_xstats_reset(struct rte_eth_dev *dev)
+{
+ struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ struct i40e_hw_port_stats *hw_stats = &pf->stats;
+
+ /* The hw registers are cleared on read */
+ pf->offset_loaded = false;
+ i40e_read_stats_registers(pf, hw);
+
+ /* reset software counters */
+ memset(hw_stats, 0, sizeof(*hw_stats));
+}
+
+static int
+i40e_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
+ unsigned n)
+{
+ struct i40e_pf *pf = I40E_DEV_PRIVATE_TO_PF(dev->data->dev_private);
+ struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private);
+ unsigned i, count = 0;
+ struct i40e_hw_port_stats *hw_stats = &pf->stats;
+
+ if(n < I40E_NB_XSTATS)
+ return I40E_NB_XSTATS;
+
+ i40e_read_stats_registers(pf, hw);
+
+ /* Reset */
+ if(xstats == NULL)
+ return 0;
+
+ /* copy 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].value = *(uint64_t *)(((char *)&hw_stats->eth) +
+ rte_i40e_stats_strings[i].offset);
+ count++;
+ }
+
+ /* copy 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].value = *(uint64_t *)(((char *)hw_stats) +
+ rte_i40e_hw_port_strings[i].offset);
+ count++;
+ }
+
+ return I40E_NB_XSTATS;
+}
+
/* Reset the statistics */
static void
i40e_dev_stats_reset(struct rte_eth_dev *dev)
--
1.9.1
Harry van Haaren
2015-09-30 09:40:21 UTC
Permalink
Add implementation of xstats() functions in i40evf PMD.

Signed-off-by: Harry van Haaren <***@intel.com>
---
drivers/net/i40e/i40e_ethdev_vf.c | 89 +++++++++++++++++++++++++++++++++++++--
1 file changed, 86 insertions(+), 3 deletions(-)

diff --git a/drivers/net/i40e/i40e_ethdev_vf.c b/drivers/net/i40e/i40e_ethdev_vf.c
index b694400..3181400 100644
--- a/drivers/net/i40e/i40e_ethdev_vf.c
+++ b/drivers/net/i40e/i40e_ethdev_vf.c
@@ -112,6 +112,9 @@ static int i40evf_dev_link_update(struct rte_eth_dev *dev,
__rte_unused int wait_to_complete);
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 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);
static void i40evf_vlan_offload_set(struct rte_eth_dev *dev, int mask);
@@ -148,6 +151,30 @@ static int i40evf_dev_rss_hash_conf_get(struct rte_eth_dev *dev,
/* Default hash key buffer for RSS */
static uint32_t rss_key_default[I40E_VFQF_HKEY_MAX_INDEX + 1];

+struct rte_i40evf_xstats_name_off {
+ char name[RTE_ETH_XSTATS_NAME_SIZE];
+ unsigned offset;
+};
+
+static const struct rte_i40evf_xstats_name_off rte_i40evf_stats_strings[] = {
+ {"rx_bytes", offsetof(struct i40e_eth_stats, rx_bytes)},
+ {"rx_unicast_packets", offsetof(struct i40e_eth_stats, rx_unicast)},
+ {"rx_multicast_packets", offsetof(struct i40e_eth_stats, rx_multicast)},
+ {"rx_broadcast_packets", offsetof(struct i40e_eth_stats, rx_broadcast)},
+ {"rx_dropped_packets", offsetof(struct i40e_eth_stats, rx_discards)},
+ {"rx_unknown_protocol_packets", offsetof(struct i40e_eth_stats,
+ rx_unknown_protocol)},
+ {"tx_bytes", offsetof(struct i40e_eth_stats, tx_bytes)},
+ {"tx_unicast_packets", offsetof(struct i40e_eth_stats, tx_bytes)},
+ {"tx_multicast_packets", offsetof(struct i40e_eth_stats, tx_bytes)},
+ {"tx_broadcast_packets", offsetof(struct i40e_eth_stats, tx_bytes)},
+ {"tx_dropped_packets", offsetof(struct i40e_eth_stats, tx_bytes)},
+ {"tx_error_packets", offsetof(struct i40e_eth_stats, tx_bytes)},
+};
+
+#define I40EVF_NB_XSTATS (sizeof(rte_i40evf_stats_strings) / \
+ sizeof(rte_i40evf_stats_strings[0]))
+
static const struct eth_dev_ops i40evf_eth_dev_ops = {
.dev_configure = i40evf_dev_configure,
.dev_start = i40evf_dev_start,
@@ -158,6 +185,8 @@ static const struct eth_dev_ops i40evf_eth_dev_ops = {
.allmulticast_disable = i40evf_dev_allmulticast_disable,
.link_update = i40evf_dev_link_update,
.stats_get = i40evf_dev_stats_get,
+ .xstats_get = i40evf_dev_xstats_get,
+ .xstats_reset = i40evf_dev_xstats_reset,
.dev_close = i40evf_dev_close,
.dev_infos_get = i40evf_dev_info_get,
.vlan_filter_set = i40evf_vlan_filter_set,
@@ -888,11 +917,10 @@ i40evf_del_mac_addr(struct rte_eth_dev *dev, struct ether_addr *addr)
}

static int
-i40evf_get_statics(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
+i40evf_update_stats(struct rte_eth_dev *dev, struct i40e_eth_stats **pstats)
{
struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
struct i40e_virtchnl_queue_select q_stats;
- struct i40e_eth_stats *pstats;
int err;
struct vf_cmd_info args;

@@ -907,9 +935,23 @@ i40evf_get_statics(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
err = i40evf_execute_vf_cmd(dev, &args);
if (err) {
PMD_DRV_LOG(ERR, "fail to execute command OP_GET_STATS");
+ *pstats = NULL;
return err;
}
- pstats = (struct i40e_eth_stats *)args.out_buffer;
+ *pstats = (struct i40e_eth_stats *)args.out_buffer;
+ return 0;
+}
+
+static int
+i40evf_get_statics(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
+{
+ int ret;
+ struct i40e_eth_stats *pstats = NULL;
+
+ ret = i40evf_update_stats(dev, &pstats);
+ if(ret != 0)
+ return 0;
+
stats->ipackets = pstats->rx_unicast + pstats->rx_multicast +
pstats->rx_broadcast;
stats->opackets = pstats->tx_broadcast + pstats->tx_multicast +
@@ -922,6 +964,47 @@ i40evf_get_statics(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
return 0;
}

+static void
+i40evf_dev_xstats_reset(struct rte_eth_dev *dev)
+{
+ struct i40e_vf *vf = I40EVF_DEV_PRIVATE_TO_VF(dev->data->dev_private);
+ struct i40e_eth_stats *pstats = NULL;
+
+ /* read stat values to clear hardware registers */
+ i40evf_update_stats(dev, &pstats);
+
+ /* set stats offset base on current values */
+ vf->vsi.eth_stats_offset = vf->vsi.eth_stats;
+}
+
+static int i40evf_dev_xstats_get(struct rte_eth_dev *dev,
+ struct rte_eth_xstats *xstats, unsigned n)
+{
+ int ret;
+ unsigned i;
+ struct i40e_eth_stats *pstats = NULL;
+
+ if(n < I40EVF_NB_XSTATS)
+ return I40EVF_NB_XSTATS;
+
+ ret = i40evf_update_stats(dev, &pstats);
+ if(ret != 0)
+ return 0;
+
+ if(!xstats)
+ return 0;
+
+ /* 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].value = *(uint64_t *)(((char *)pstats) +
+ rte_i40evf_stats_strings[i].offset);
+ }
+
+ return I40EVF_NB_XSTATS;
+}
+
static int
i40evf_add_vlan(struct rte_eth_dev *dev, uint16_t vlanid)
{
--
1.9.1
Harry van Haaren
2015-09-30 09:40:22 UTC
Permalink
Add xstats() functions and statistic strings.

Signed-off-by: Harry van Haaren <***@intel.com>
---
drivers/net/fm10k/fm10k_ethdev.c | 69 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 69 insertions(+)

diff --git a/drivers/net/fm10k/fm10k_ethdev.c b/drivers/net/fm10k/fm10k_ethdev.c
index a69c990..2d92fd3 100644
--- a/drivers/net/fm10k/fm10k_ethdev.c
+++ b/drivers/net/fm10k/fm10k_ethdev.c
@@ -68,6 +68,37 @@ fm10k_MACVLAN_remove_all(struct rte_eth_dev *dev);
static void fm10k_tx_queue_release(void *queue);
static void fm10k_rx_queue_release(void *queue);

+struct rte_fm10k_xstats_name_off {
+ char name[RTE_ETH_XSTATS_NAME_SIZE];
+ unsigned offset;
+};
+
+struct rte_fm10k_xstats_name_off rte_fm10k_hw_stats_strings[] = {
+ {"completion_timeout_count", offsetof(struct fm10k_hw_stats, timeout)},
+ {"unsupported_requests_count", offsetof(struct fm10k_hw_stats, ur)},
+ {"completer_abort_count", offsetof(struct fm10k_hw_stats, ca)},
+ {"unsupported_message_count", offsetof(struct fm10k_hw_stats, um)},
+ {"checksum_error_count", offsetof(struct fm10k_hw_stats, xec)},
+ {"vlan_dropped", offsetof(struct fm10k_hw_stats, vlan_drop)},
+ {"loopback_dropped", offsetof(struct fm10k_hw_stats, loopback_drop)},
+ {"no_descriptor_dropped", offsetof(struct fm10k_hw_stats, nodesc_drop)},
+};
+
+struct rte_fm10k_xstats_name_off rte_fm10k_hw_stats_q_strings[] = {
+ {"tx_q_bytes", offsetof(struct fm10k_hw_stats_q, tx_bytes)},
+ {"tx_q_packets", offsetof(struct fm10k_hw_stats_q, tx_packets)},
+ {"rx_q_bytes", offsetof(struct fm10k_hw_stats_q, rx_bytes)},
+ {"rx_q_packets", offsetof(struct fm10k_hw_stats_q, rx_packets)},
+ {"rx_q_dropped", offsetof(struct fm10k_hw_stats_q, rx_drops)},
+};
+
+#define FM10K_NB_HW_XSTATS (sizeof(rte_fm10k_hw_stats_strings) / \
+ sizeof(rte_fm10k_hw_stats_strings[0]))
+#define FM10K_NB_Q_XSTATS (sizeof(rte_fm10k_hw_stats_q_strings) / \
+ sizeof(rte_fm10k_hw_stats_q_strings[0]))
+#define FM10K_NB_XSTATS (FM10K_NB_HW_XSTATS + FM10K_NB_Q_XSTATS * \
+ FM10K_MAX_QUEUES_PF)
+
static void
fm10k_mbx_initlock(struct fm10k_hw *hw)
{
@@ -867,6 +898,42 @@ fm10k_link_update(struct rte_eth_dev *dev,
return 0;
}

+static int
+fm10k_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstats *xstats,
+ unsigned n)
+{
+ struct fm10k_hw_stats *hw_stats =
+ FM10K_DEV_PRIVATE_TO_STATS(dev->data->dev_private);
+ unsigned i, q, count = 0;
+
+ if(n < FM10K_NB_XSTATS)
+ return FM10K_NB_XSTATS;
+
+ /* Global stats */
+ for(i = 0; i < FM10K_NB_HW_XSTATS; i++) {
+ snprintf(xstats[count].name, sizeof(xstats[count].name),
+ "%s", rte_fm10k_hw_stats_strings[count].name);
+ xstats[count].value = *(uint64_t *)(((char *)hw_stats) +
+ rte_fm10k_hw_stats_strings[count].offset);
+ count++;
+ }
+
+ /* PF queue stats */
+ for(q = 0; q < FM10K_MAX_QUEUES_PF; q++) {
+ for(i = 0; i < FM10K_NB_Q_XSTATS; i++) {
+ snprintf(xstats[count].name, sizeof(xstats[count].name),
+ "rx_q%u_%s", q,
+ rte_fm10k_hw_stats_q_strings[i].name);
+ xstats[count].value =
+ *(uint64_t *)(((char *)&hw_stats->q[q]) +
+ rte_fm10k_hw_stats_q_strings[i].offset);
+ count++;
+ }
+ }
+
+ return FM10K_NB_XSTATS;
+}
+
static void
fm10k_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
{
@@ -2034,7 +2101,9 @@ static const struct eth_dev_ops fm10k_eth_dev_ops = {
.allmulticast_enable = fm10k_dev_allmulticast_enable,
.allmulticast_disable = fm10k_dev_allmulticast_disable,
.stats_get = fm10k_stats_get,
+ .xstats_get = fm10k_xstats_get,
.stats_reset = fm10k_stats_reset,
+ .xstats_reset = fm10k_stats_reset,
.link_update = fm10k_link_update,
.dev_infos_get = fm10k_dev_infos_get,
.vlan_filter_set = fm10k_vlan_filter_set,
--
1.9.1
Continue reading on narkive:
Loading...