net/vmxnet3: implement extended stats
authorRobert Shearman <rshearma@brocade.com>
Thu, 15 Jun 2017 12:16:09 +0000 (08:16 -0400)
committerFerruh Yigit <ferruh.yigit@intel.com>
Thu, 6 Jul 2017 13:00:57 +0000 (15:00 +0200)
Implement xstats_get() to allow a number of driver-specific Tx and Rx
stats to be retrieved.

Signed-off-by: Robert Shearman <rshearma@brocade.com>
Acked-by: Shrikrishna Khare <skhare@vmware.com>
doc/guides/nics/features/vmxnet3.ini
drivers/net/vmxnet3/vmxnet3_ethdev.c

index 8f7f8e0..9a11513 100644 (file)
@@ -21,6 +21,7 @@ VLAN offload         = Y
 L4 checksum offload  = Y
 Packet type parsing  = Y
 Basic stats          = Y
+Extended stats       = Y
 Stats per queue      = Y
 Linux UIO            = Y
 Linux VFIO           = Y
index 1301f50..f5a9832 100644 (file)
@@ -88,6 +88,11 @@ static int vmxnet3_dev_link_update(struct rte_eth_dev *dev,
 static void vmxnet3_hw_stats_save(struct vmxnet3_hw *hw);
 static void vmxnet3_dev_stats_get(struct rte_eth_dev *dev,
                                  struct rte_eth_stats *stats);
+static int vmxnet3_dev_xstats_get_names(struct rte_eth_dev *dev,
+                                       struct rte_eth_xstat_name *xstats,
+                                       unsigned int n);
+static int vmxnet3_dev_xstats_get(struct rte_eth_dev *dev,
+                                 struct rte_eth_xstat *xstats, unsigned int n);
 static void vmxnet3_dev_info_get(struct rte_eth_dev *dev,
                                 struct rte_eth_dev_info *dev_info);
 static const uint32_t *
@@ -122,6 +127,8 @@ static const struct eth_dev_ops vmxnet3_eth_dev_ops = {
        .allmulticast_disable = vmxnet3_dev_allmulticast_disable,
        .link_update          = vmxnet3_dev_link_update,
        .stats_get            = vmxnet3_dev_stats_get,
+       .xstats_get_names     = vmxnet3_dev_xstats_get_names,
+       .xstats_get           = vmxnet3_dev_xstats_get,
        .mac_addr_set         = vmxnet3_mac_addr_set,
        .dev_infos_get        = vmxnet3_dev_info_get,
        .dev_supported_ptypes_get = vmxnet3_dev_supported_ptypes_get,
@@ -133,6 +140,27 @@ static const struct eth_dev_ops vmxnet3_eth_dev_ops = {
        .tx_queue_release     = vmxnet3_dev_tx_queue_release,
 };
 
+struct vmxnet3_xstats_name_off {
+       char name[RTE_ETH_XSTATS_NAME_SIZE];
+       unsigned int offset;
+};
+
+/* tx_qX_ is prepended to the name string here */
+static const struct vmxnet3_xstats_name_off vmxnet3_txq_stat_strings[] = {
+       {"drop_total",         offsetof(struct vmxnet3_txq_stats, drop_total)},
+       {"drop_too_many_segs", offsetof(struct vmxnet3_txq_stats, drop_too_many_segs)},
+       {"drop_tso",           offsetof(struct vmxnet3_txq_stats, drop_tso)},
+       {"tx_ring_full",       offsetof(struct vmxnet3_txq_stats, tx_ring_full)},
+};
+
+/* rx_qX_ is prepended to the name string here */
+static const struct vmxnet3_xstats_name_off vmxnet3_rxq_stat_strings[] = {
+       {"drop_total",           offsetof(struct vmxnet3_rxq_stats, drop_total)},
+       {"drop_err",             offsetof(struct vmxnet3_rxq_stats, drop_err)},
+       {"drop_fcs",             offsetof(struct vmxnet3_rxq_stats, drop_fcs)},
+       {"rx_buf_alloc_failure", offsetof(struct vmxnet3_rxq_stats, rx_buf_alloc_failure)},
+};
+
 static const struct rte_memzone *
 gpa_zone_reserve(struct rte_eth_dev *dev, uint32_t size,
                 const char *post_string, int socket_id,
@@ -882,6 +910,91 @@ vmxnet3_hw_stats_save(struct vmxnet3_hw *hw)
                vmxnet3_hw_rx_stats_get(hw, i, &hw->saved_rx_stats[i]);
 }
 
+static int
+vmxnet3_dev_xstats_get_names(struct rte_eth_dev *dev,
+                            struct rte_eth_xstat_name *xstats_names,
+                            unsigned int n)
+{
+       unsigned int i, t, count = 0;
+       unsigned int nstats =
+               dev->data->nb_tx_queues * RTE_DIM(vmxnet3_txq_stat_strings) +
+               dev->data->nb_rx_queues * RTE_DIM(vmxnet3_rxq_stat_strings);
+
+       if (!xstats_names || n < nstats)
+               return nstats;
+
+       for (i = 0; i < dev->data->nb_rx_queues; i++) {
+               if (!dev->data->rx_queues[i])
+                       continue;
+
+               for (t = 0; t < RTE_DIM(vmxnet3_rxq_stat_strings); t++) {
+                       snprintf(xstats_names[count].name,
+                                sizeof(xstats_names[count].name),
+                                "rx_q%u_%s", i,
+                                vmxnet3_rxq_stat_strings[t].name);
+                       count++;
+               }
+       }
+
+       for (i = 0; i < dev->data->nb_tx_queues; i++) {
+               if (!dev->data->tx_queues[i])
+                       continue;
+
+               for (t = 0; t < RTE_DIM(vmxnet3_txq_stat_strings); t++) {
+                       snprintf(xstats_names[count].name,
+                                sizeof(xstats_names[count].name),
+                                "tx_q%u_%s", i,
+                                vmxnet3_txq_stat_strings[t].name);
+                       count++;
+               }
+       }
+
+       return count;
+}
+
+static int
+vmxnet3_dev_xstats_get(struct rte_eth_dev *dev, struct rte_eth_xstat *xstats,
+                      unsigned int n)
+{
+       unsigned int i, t, count = 0;
+       unsigned int nstats =
+               dev->data->nb_tx_queues * RTE_DIM(vmxnet3_txq_stat_strings) +
+               dev->data->nb_rx_queues * RTE_DIM(vmxnet3_rxq_stat_strings);
+
+       if (n < nstats)
+               return nstats;
+
+       for (i = 0; i < dev->data->nb_rx_queues; i++) {
+               struct vmxnet3_rx_queue *rxq = dev->data->rx_queues[i];
+
+               if (rxq == NULL)
+                       continue;
+
+               for (t = 0; t < RTE_DIM(vmxnet3_rxq_stat_strings); t++) {
+                       xstats[count].value = *(uint64_t *)(((char *)&rxq->stats) +
+                               vmxnet3_rxq_stat_strings[t].offset);
+                       xstats[count].id = count;
+                       count++;
+               }
+       }
+
+       for (i = 0; i < dev->data->nb_tx_queues; i++) {
+               struct vmxnet3_tx_queue *txq = dev->data->tx_queues[i];
+
+               if (txq == NULL)
+                       continue;
+
+               for (t = 0; t < RTE_DIM(vmxnet3_txq_stat_strings); t++) {
+                       xstats[count].value = *(uint64_t *)(((char *)&txq->stats) +
+                               vmxnet3_txq_stat_strings[t].offset);
+                       xstats[count].id = count;
+                       count++;
+               }
+       }
+
+       return count;
+}
+
 static void
 vmxnet3_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
 {