[ofa-general] [PATCH RFCv2 1/2] RDMA: Add protocol statistics attributes to the RDMA sysfs.
Steve Wise
swise at opengridcomputing.com
Tue Jun 17 14:38:56 PDT 2008
This patch adds a sysfs attribute group called "proto_stats" under
/sys/class/infiniband/$device/ and populates this group with protocol
statistics if they exist for a given device. Currently, only iWARP
stats are defined, but the code is designed to allow Infiniband protocol
stats if they become available. These stats are per-device and more
importantly -not- per port.
Details:
- Add union rdma_protocol_stats in ib_verbs.h. This union allows defining
transport-specific stats. Currently only iwarp stats are defined.
- Add struct iw_protocol_stats to define the current set of iwarp protocol
stats.
- Add new ib_device method called get_proto_stats() to return protocol
statistics.
- Add logic in core/sysfs.c to create iwarp protocol stats attributes
if the device is an RNIC and has a get_proto_stats() method.
Signed-off-by: Steve Wise <swise at opengridcomputing.com>
---
drivers/infiniband/core/sysfs.c | 102 +++++++++++++++++++++++++++++++++++++++
include/rdma/ib_verbs.h | 39 +++++++++++++++
2 files changed, 141 insertions(+), 0 deletions(-)
diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c
index 9575655..97bdbe7 100644
--- a/drivers/infiniband/core/sysfs.c
+++ b/drivers/infiniband/core/sysfs.c
@@ -665,6 +665,103 @@ static struct class ib_class = {
.dev_uevent = ib_device_uevent,
};
+/* Show a given an attribute in the statistics group */
+static ssize_t show_protocol_stat(const struct device *device,
+ struct device_attribute *attr, char *buf,
+ int width, unsigned offset)
+{
+ struct ib_device *dev = container_of(device, struct ib_device, dev);
+ union rdma_protocol_stats stats;
+ ssize_t ret = -EINVAL;
+
+ WARN_ON(offset > sizeof(union rdma_protocol_stats) ||
+ offset % (width == 32 ? 4 : 8) != 0);
+
+ if (!dev->get_protocol_stats)
+ goto out;
+ ret = (*dev->get_protocol_stats)(dev, &stats);
+ if (ret)
+ goto out;
+ if (width == 32)
+ ret = sprintf(buf, "%u\n", *(u32 *)(((u8 *)&stats) + offset));
+ else if (width == 64)
+ ret = sprintf(buf, "%llu\n", *(u64 *)(((u8 *)&stats) + offset));
+ else
+ goto out;
+out:
+ return ret;
+}
+
+/* generate a read-only iwarp statistics attribute */
+#define IW_STATS_ENTRY(name, width) \
+static ssize_t show_##name(struct device *device, \
+ struct device_attribute *attr, char *buf) \
+{ \
+ return show_protocol_stat(device, attr, buf, width, \
+ offsetof(struct iw_protocol_stats, name)); \
+} \
+static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL)
+
+IW_STATS_ENTRY(tcpInSegs, 64);
+IW_STATS_ENTRY(tcpOutSegs, 64);
+IW_STATS_ENTRY(tcpRetransSeg, 64);
+IW_STATS_ENTRY(tcpInErrs, 64);
+IW_STATS_ENTRY(tcpActiveOpens, 32);
+IW_STATS_ENTRY(tcpPassiveOpens, 32);
+IW_STATS_ENTRY(tcpAttemptFails, 32);
+IW_STATS_ENTRY(tcpEstabResets, 32);
+IW_STATS_ENTRY(tcpOutRsts, 32);
+IW_STATS_ENTRY(tcpCurrEstab, 32);
+IW_STATS_ENTRY(tcpRtoMin, 32);
+IW_STATS_ENTRY(tcpRtoMax, 32);
+IW_STATS_ENTRY(ipInReceive, 64);
+IW_STATS_ENTRY(ipInHdrErrors, 64);
+IW_STATS_ENTRY(ipInAddrErrors, 64);
+IW_STATS_ENTRY(ipInUnknownProtos, 64);
+IW_STATS_ENTRY(ipInDiscards, 64);
+IW_STATS_ENTRY(ipInDelivers, 64);
+IW_STATS_ENTRY(ipOutRequests, 64);
+IW_STATS_ENTRY(ipOutDiscards, 64);
+IW_STATS_ENTRY(ipOutNoRoutes, 64);
+IW_STATS_ENTRY(ipReasmTimeout, 32);
+IW_STATS_ENTRY(ipReasmReqds, 32);
+IW_STATS_ENTRY(ipReasmOKs, 32);
+IW_STATS_ENTRY(ipReasmFails, 32);
+
+static struct attribute *iw_proto_stats_attrs[] = {
+ &dev_attr_tcpInSegs.attr,
+ &dev_attr_tcpOutSegs.attr,
+ &dev_attr_tcpRetransSeg.attr,
+ &dev_attr_tcpInErrs.attr,
+ &dev_attr_tcpActiveOpens.attr,
+ &dev_attr_tcpPassiveOpens.attr,
+ &dev_attr_tcpAttemptFails.attr,
+ &dev_attr_tcpEstabResets.attr,
+ &dev_attr_tcpOutRsts.attr,
+ &dev_attr_tcpCurrEstab.attr,
+ &dev_attr_tcpRtoMin.attr,
+ &dev_attr_tcpRtoMax.attr,
+ &dev_attr_ipInReceive.attr,
+ &dev_attr_ipInHdrErrors.attr,
+ &dev_attr_ipInAddrErrors.attr,
+ &dev_attr_ipInUnknownProtos.attr,
+ &dev_attr_ipInDiscards.attr,
+ &dev_attr_ipInDelivers.attr,
+ &dev_attr_ipOutRequests.attr,
+ &dev_attr_ipOutDiscards.attr,
+ &dev_attr_ipOutNoRoutes.attr,
+ &dev_attr_ipReasmTimeout.attr,
+ &dev_attr_ipReasmReqds.attr,
+ &dev_attr_ipReasmOKs.attr,
+ &dev_attr_ipReasmFails.attr,
+ NULL
+};
+
+static struct attribute_group iw_stats_group = {
+ .name = "proto_stats",
+ .attrs = iw_proto_stats_attrs,
+};
+
int ib_device_register_sysfs(struct ib_device *device)
{
struct device *class_dev = &device->dev;
@@ -707,6 +804,11 @@ int ib_device_register_sysfs(struct ib_device *device)
}
}
+ if (device->node_type == RDMA_NODE_RNIC && device->get_protocol_stats) {
+ ret = sysfs_create_group(&class_dev->kobj, &iw_stats_group);
+ if (ret)
+ goto err_put;
+ }
return 0;
err_put:
diff --git a/include/rdma/ib_verbs.h b/include/rdma/ib_verbs.h
index 62e5bcd..0260645 100644
--- a/include/rdma/ib_verbs.h
+++ b/include/rdma/ib_verbs.h
@@ -53,6 +53,43 @@
#include <asm/atomic.h>
#include <asm/uaccess.h>
+struct ib_protocol_stats {
+ /* TBD... */
+};
+
+struct iw_protocol_stats {
+ u64 tcpInSegs;
+ u64 tcpOutSegs;
+ u64 tcpRetransSeg;
+ u64 tcpInErrs;
+ u32 tcpActiveOpens;
+ u32 tcpPassiveOpens;
+ u32 tcpAttemptFails;
+ u32 tcpEstabResets;
+ u32 tcpOutRsts;
+ u32 tcpCurrEstab;
+ u32 tcpRtoMin;
+ u32 tcpRtoMax;
+ u64 ipInReceive;
+ u64 ipInHdrErrors;
+ u64 ipInAddrErrors;
+ u64 ipInUnknownProtos;
+ u64 ipInDiscards;
+ u64 ipInDelivers;
+ u64 ipOutRequests;
+ u64 ipOutDiscards;
+ u64 ipOutNoRoutes;
+ u32 ipReasmTimeout;
+ u32 ipReasmReqds;
+ u32 ipReasmOKs;
+ u32 ipReasmFails;
+};
+
+union rdma_protocol_stats {
+ struct ib_protocol_stats ib;
+ struct iw_protocol_stats iw;
+};
+
union ib_gid {
u8 raw[16];
struct {
@@ -947,6 +984,8 @@ struct ib_device {
struct iw_cm_verbs *iwcm;
+ int (*get_protocol_stats)(struct ib_device *device,
+ union rdma_protocol_stats *stats);
int (*query_device)(struct ib_device *device,
struct ib_device_attr *device_attr);
int (*query_port)(struct ib_device *device,
More information about the general
mailing list