IB/ipoib: Add readout of statistics using ethtool
authorHans Westgaard Ry <hans.westgaard.ry@oracle.com>
Thu, 21 Apr 2016 11:13:21 +0000 (13:13 +0200)
committerDoug Ledford <dledford@redhat.com>
Fri, 13 May 2016 23:39:43 +0000 (19:39 -0400)
IPoIB collects statistics of traffic including number of packets
sent/received, number of bytes transferred, and certain errors. This
patch makes these statistics available to be queried by ethtool.

Signed-off-by: Hans Westgaard Ry <hans.westgaard.ry@oracle.com>
Reviewed-by: Yuval Shaia <yuval.shaia@oracle.com>
Reviewed-by: Santosh Shilimkar <santosh.shilimkar@oracle.com>
Tested-by: Yuval Shaia <yuval.shaia@oracle.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
drivers/infiniband/ulp/ipoib/ipoib_ethtool.c

index a53fa5fc0dec7d65900cce1133b2d4e2326183cc..1502199c8e56272584e7fb5797031f369a67fcd2 100644 (file)
 
 #include "ipoib.h"
 
+struct ipoib_stats {
+       char stat_string[ETH_GSTRING_LEN];
+       int stat_offset;
+};
+
+#define IPOIB_NETDEV_STAT(m) { \
+               .stat_string = #m, \
+               .stat_offset = offsetof(struct rtnl_link_stats64, m) }
+
+static const struct ipoib_stats ipoib_gstrings_stats[] = {
+       IPOIB_NETDEV_STAT(rx_packets),
+       IPOIB_NETDEV_STAT(tx_packets),
+       IPOIB_NETDEV_STAT(rx_bytes),
+       IPOIB_NETDEV_STAT(tx_bytes),
+       IPOIB_NETDEV_STAT(tx_errors),
+       IPOIB_NETDEV_STAT(rx_dropped),
+       IPOIB_NETDEV_STAT(tx_dropped)
+};
+
+#define IPOIB_GLOBAL_STATS_LEN ARRAY_SIZE(ipoib_gstrings_stats)
+
 static void ipoib_get_drvinfo(struct net_device *netdev,
                              struct ethtool_drvinfo *drvinfo)
 {
@@ -92,11 +113,57 @@ static int ipoib_set_coalesce(struct net_device *dev,
 
        return 0;
 }
+static void ipoib_get_ethtool_stats(struct net_device *dev,
+                                   struct ethtool_stats __always_unused *stats,
+                                   u64 *data)
+{
+       int i;
+       struct net_device_stats *net_stats = &dev->stats;
+       u8 *p = (u8 *)net_stats;
+
+       for (i = 0; i < IPOIB_GLOBAL_STATS_LEN; i++)
+               data[i] = *(u64 *)(p + ipoib_gstrings_stats[i].stat_offset);
+
+}
+static void ipoib_get_strings(struct net_device __always_unused *dev,
+                             u32 stringset, u8 *data)
+{
+       u8 *p = data;
+       int i;
+
+       switch (stringset) {
+       case ETH_SS_STATS:
+               for (i = 0; i < IPOIB_GLOBAL_STATS_LEN; i++) {
+                       memcpy(p, ipoib_gstrings_stats[i].stat_string,
+                               ETH_GSTRING_LEN);
+                       p += ETH_GSTRING_LEN;
+               }
+               break;
+       case ETH_SS_TEST:
+       default:
+               break;
+       }
+}
+static int ipoib_get_sset_count(struct net_device __always_unused *dev,
+                                int sset)
+{
+       switch (sset) {
+       case ETH_SS_STATS:
+               return IPOIB_GLOBAL_STATS_LEN;
+       case ETH_SS_TEST:
+       default:
+               break;
+       }
+       return -EOPNOTSUPP;
+}
 
 static const struct ethtool_ops ipoib_ethtool_ops = {
        .get_drvinfo            = ipoib_get_drvinfo,
        .get_coalesce           = ipoib_get_coalesce,
        .set_coalesce           = ipoib_set_coalesce,
+       .get_strings            = ipoib_get_strings,
+       .get_ethtool_stats      = ipoib_get_ethtool_stats,
+       .get_sset_count         = ipoib_get_sset_count,
 };
 
 void ipoib_set_ethtool_ops(struct net_device *dev)