Port the kernel madeye utility to user space.  Use the
new MAD snooping ability exported from the kernel to
view captured MADs and display them.

Signed-off-by: Sean Hefty <[email protected]>
---
 infiniband-diags/Makefile.am              |    6
 infiniband-diags/configure.in             |    3
 infiniband-diags/infiniband-diags.spec.in |    1
 infiniband-diags/man/madeye.8             |   23 +
 infiniband-diags/src/madeye.c             |  582 +++++++++++++++++++++++++++++
 5 files changed, 613 insertions(+), 2 deletions(-)
 create mode 100644 infiniband-diags/man/madeye.8
 create mode 100755 infiniband-diags/src/madeye.c

diff --git a/infiniband-diags/Makefile.am b/infiniband-diags/Makefile.am
index af90b05..e0a55ef 100644
--- a/infiniband-diags/Makefile.am
+++ b/infiniband-diags/Makefile.am
@@ -13,7 +13,7 @@ sbin_PROGRAMS = src/ibaddr src/ibnetdiscover src/ibping 
src/ibportstate \
                src/ibroute src/ibstat src/ibsysstat src/ibtracert \
                src/perfquery src/sminfo src/smpdump src/smpquery \
                src/saquery src/vendstat src/iblinkinfo \
-               src/ibqueryerrors src/ibcacheedit
+               src/ibqueryerrors src/ibcacheedit src/madeye

 if ENABLE_TEST_UTILS
 sbin_PROGRAMS += src/ibsendtrap src/mcm_rereg_test
@@ -55,6 +55,8 @@ src_sminfo_SOURCES = src/sminfo.c
 src_smpdump_SOURCES = src/smpdump.c
 src_smpquery_SOURCES = src/smpquery.c
 src_saquery_SOURCES = src/saquery.c
+src_madeye_SOURCES = src/madeye.c
+src_madeye_LDFLAGS = -libumad
 src_ibsendtrap_SOURCES = src/ibsendtrap.c
 src_vendstat_SOURCES = src/vendstat.c
 src_mcm_rereg_test_SOURCES = src/mcm_rereg_test.c
@@ -78,7 +80,7 @@ man_MANS = man/ibaddr.8 man/ibcheckerrors.8 man/ibcheckerrs.8 
\
        man/ibprintswitch.8 man/ibprintca.8 man/ibfindnodesusing.8 \
        man/ibdatacounts.8 man/ibdatacounters.8 \
        man/ibrouters.8 man/ibprintrt.8 man/ibidsverify.8 \
-       man/check_lft_balance.8 man/ibcacheedit.8
+       man/check_lft_balance.8 man/ibcacheedit.8 man/madeye.8

 BUILT_SOURCES = ibdiag_version
 ibdiag_version:
diff --git a/infiniband-diags/configure.in b/infiniband-diags/configure.in
index b9326c0..e01b5a8 100644
--- a/infiniband-diags/configure.in
+++ b/infiniband-diags/configure.in
@@ -50,6 +50,9 @@ then
 AC_CHECK_HEADER(infiniband/umad.h, [],
        AC_MSG_ERROR([<infiniband/umad.h> not found. diags require libibumad.])
 )
+AC_CHECK_HEADER(infiniband/umad_types.h, [],
+       AC_MSG_ERROR([<infiniband/umad_types.h> not found. diags require more 
recent libibumad.])
+)
 AC_CHECK_HEADER(infiniband/mad.h, [],
        AC_MSG_ERROR([<infiniband/mad.h> not found. diags require libibmad.])
 )
diff --git a/infiniband-diags/infiniband-diags.spec.in 
b/infiniband-diags/infiniband-diags.spec.in
index c50ce09..64cc645 100644
--- a/infiniband-diags/infiniband-diags.spec.in
+++ b/infiniband-diags/infiniband-diags.spec.in
@@ -47,6 +47,7 @@ rm -rf $RPM_BUILD_ROOT
 %{_sbindir}/check_lft_balance.pl
 %{_sbindir}/set_nodedesc.sh
 %{_sbindir}/sm*
+%{_sbindir}/madeye
 %{_libdir}/*.a
 %{_libdir}/*.so*
 %{_includedir}/infiniband/*.h
diff --git a/infiniband-diags/man/madeye.8 b/infiniband-diags/man/madeye.8
new file mode 100644
index 0000000..ec26da2
--- /dev/null
+++ b/infiniband-diags/man/madeye.8
@@ -0,0 +1,23 @@
+.TH MADEYE 8 "October 22, 2010" "OpenIB" "OpenIB Diagnostics"
+
+.SH NAME
+madeye \- capture and display captured IB MAD traffic
+
+.SH SYNOPSIS
+.B madeye
+[\-C, \-\-Ca=<ca_name>] [\-P, \-\-Port=<port_number>]
+[\-c, \-\-class=<management_class>] [\-n, \-\-class_version=<class_version>]
+[\-a, \-\-attr=<attribute_id>]
+[\-e, \-\-errors] [\-o, \-\-oui=<oui>] [\-h, \-\-help]
+[\-v, \-\-verbose]
+
+.SH DESCRIPTION
+.PP
+Madeye registers with the kernel to capture specified sent and
+received MADs.  Captured MADs are displayed in a human readable
+format.
+
+.SH AUTHOR
+.TP
+Sean Hefty
+.RI < [email protected] >
diff --git a/infiniband-diags/src/madeye.c b/infiniband-diags/src/madeye.c
new file mode 100755
index 0000000..684ede4
--- /dev/null
+++ b/infiniband-diags/src/madeye.c
@@ -0,0 +1,582 @@
+/*
+ * Copyright (c) 2004, 2005, 2010 Intel Corporation.  All rights reserved.
+ * Copyright (c) 2005 Voltaire Inc.  All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses.  You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directorY of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ *     Redistribution and use in source and binary forms, with or
+ *     without modification, are permitted provided that the following
+ *     conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#if HAVE_CONFIG_H
+#  include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdio.h>
+#include <getopt.h>
+#include <string.h>
+
+#include <infiniband/umad.h>
+#include <infiniband/umad_sa.h>
+#include <infiniband/umad_sm.h>
+#include <infiniband/umad_cm.h>
+
+struct mad_info {
+       ib_user_mad_t   user_mad;
+       char            data[256];
+};
+
+static char *ca;
+static uint8_t port;
+static umad_filter_t filter;
+static int verbose;
+
+static char * get_class_name(uint8_t mgmt_class)
+{
+       switch(mgmt_class) {
+       case UMAD_CLASS_SUBN_LID_ROUTED:
+               return "LID routed SMP";
+       case UMAD_CLASS_SUBN_DIRECTED_ROUTE:
+               return "Directed route SMP";
+       case UMAD_CLASS_SUBN_ADM:
+               return "Subnet admin.";
+       case UMAD_CLASS_PERF_MGMT:
+               return "Perf. mgmt.";
+       case UMAD_CLASS_BM:
+               return "Baseboard mgmt.";
+       case UMAD_CLASS_DEVICE_MGMT:
+               return "Device mgmt.";
+       case UMAD_CLASS_CM:
+               return "Comm. mgmt.";
+       case UMAD_CLASS_SNMP:
+               return "SNMP";
+       default:
+               return "Unknown vendor/application";
+       }
+}
+
+static char * get_method_name(uint8_t mgmt_class, uint8_t method)
+{
+       switch(method) {
+       case UMAD_METHOD_GET:
+               return "Get";
+       case UMAD_METHOD_SET:
+               return "Set";
+       case UMAD_METHOD_GET_RESP:
+               return "Get response";
+       case UMAD_METHOD_SEND:
+               return "Send";
+       case UMAD_METHOD_TRAP:
+               return "Trap";
+       case UMAD_METHOD_REPORT:
+               return "Report";
+       case UMAD_METHOD_REPORT_RESP:
+               return "Report response";
+       case UMAD_METHOD_TRAP_REPRESS:
+               return "Trap repress";
+       default:
+               break;
+       }
+
+       switch (mgmt_class) {
+       case UMAD_CLASS_SUBN_ADM:
+               switch (method) {
+               case UMAD_SA_METHOD_GET_TABLE:
+                       return "Get table";
+               case UMAD_SA_METHOD_GET_TABLE_RESP:
+                       return "Get table response";
+               case UMAD_SA_METHOD_DELETE:
+                       return "Delete";
+               case UMAD_SA_METHOD_DELETE_RESP:
+                       return "Delete response";
+               case UMAD_SA_METHOD_GET_MULTI:
+                       return "Get Multi";
+               case UMAD_SA_METHOD_GET_MULTI_RESP:
+                       return "Get Multi response";
+               case UMAD_SA_METHOD_GET_TRACE_TABLE:
+                       return "Get Trace Table response";
+               default:
+                       break;
+               }
+       default:
+               break;
+       }
+
+       return "Unknown";
+}
+
+static void print_status_details(uint16_t status)
+{
+       if (status & 0x0001)
+               printf("               busy\n");
+       if (status & 0x0002)
+               printf("               redirection required\n");
+       switch((status & 0x001C) >> 2) {
+       case 1:
+               printf("               bad version\n");
+               break;
+       case 2:
+               printf("               method not supported\n");
+               break;
+       case 3:
+               printf("               method/attribute combo not supported\n");
+               break;
+       case 7:
+               printf("               invalid attribute/modifier value\n");
+               break;
+       }
+}
+
+static char * get_sa_attr(uint16_t attr)
+{
+       switch(attr) {
+       case UMAD_ATTR_CLASS_PORT_INFO:
+               return "Class Port Info";
+       case UMAD_ATTR_NOTICE:
+               return "Notice";
+       case UMAD_ATTR_INFORM_INFO:
+               return "Inform Info";
+       case UMAD_SA_ATTR_NODE_REC:
+               return "Node Record";
+       case UMAD_SA_ATTR_PORT_INFO_REC:
+               return "PortInfo Record";
+       case UMAD_SA_ATTR_SLVL_REC:
+               return "SL to VL Record";
+       case UMAD_SA_ATTR_SWITCH_INFO_REC:
+               return "Switch Record";
+       case UMAD_SA_ATTR_LINEAR_FT_REC:
+               return "Linear FDB Record";
+       case UMAD_SA_ATTR_RANDOM_FT_REC:
+               return "Random FDB Record";
+       case UMAD_SA_ATTR_MCAST_FT_REC:
+               return "Multicast FDB Record";
+       case UMAD_SA_ATTR_SM_INFO_REC:
+               return "SM Info Record";
+       case UMAD_SA_ATTR_INFORM_INFO_REC:
+               return "Inform Info Record";
+       case UMAD_SA_ATTR_LINK_REC:
+               return "Link Record";
+       case UMAD_SA_ATTR_GUID_INFO_REC:
+               return "Guid Info Record";
+       case UMAD_SA_ATTR_SERVICE_REC:
+               return "Service Record";
+       case UMAD_SA_ATTR_PKEY_TABLE_REC:
+               return "Partition Record";
+       case UMAD_SA_ATTR_PATH_REC:
+               return "Path Record";
+       case UMAD_SA_ATTR_VL_ARB_REC:
+               return "VL Arb Record";
+       case UMAD_SA_ATTR_MCMEMBER_REC:
+               return "MC Member Record";
+       case UMAD_SA_ATTR_TRACE_REC:
+               return "Trace Record";
+       case UMAD_SA_ATTR_MULTI_PATH_REC:
+               return "Multi Path Record";
+       case UMAD_SA_ATTR_SERVICE_ASSOC_REC:
+               return "Service Assoc Record";
+       default:
+               return "";
+       }
+}
+
+static char * get_cm_attr(uint16_t attr)
+{
+       switch(attr) {
+       case UMAD_CM_ATTR_REQ:
+               return "REQ";
+       case UMAD_CM_ATTR_MRA:
+               return "MRA";
+       case UMAD_CM_ATTR_REJ:
+               return "REJ";
+       case UMAD_CM_ATTR_REP:
+               return "REP";
+       case UMAD_CM_ATTR_RTU:
+               return "RTU";
+       case UMAD_CM_ATTR_DREQ:
+               return "DREQ";
+       case UMAD_CM_ATTR_DREP:
+               return "DREP";
+       case UMAD_CM_ATTR_SIDR_REQ:
+               return "SIDR REQ";
+       case UMAD_CM_ATTR_SIDR_REP:
+               return "SIDR REP";
+       case UMAD_CM_ATTR_LAP:
+               return "LAP";
+       case UMAD_CM_ATTR_APR:
+               return "APR";
+       default:
+               return "unknown";
+       }
+}
+
+static void print_mad_hdr(struct umad_hdr *hdr)
+{
+       printf("MAD version....0x%01x\n", hdr->base_version);
+       printf("Class..........0x%01x (%s)\n", hdr->mgmt_class,
+              get_class_name(hdr->mgmt_class));
+       printf("Class version..0x%01x\n", hdr->class_version);
+       printf("Method.........0x%01x (%s)\n", hdr->method,
+              get_method_name(hdr->mgmt_class, hdr->method));
+       printf("Status.........0x%02x\n", ntohs(hdr->status));
+       if (hdr->status)
+               print_status_details(ntohs(hdr->status));
+       printf("Class specific.0x%02x\n", ntohs(hdr->class_specific));
+       printf("Trans ID.......0x%llx\n", (unsigned long long) 
ntohll(hdr->tid));
+       printf("Attr ID........0x%02x", ntohs(hdr->attr_id));
+       switch (hdr->mgmt_class) {
+       case UMAD_CLASS_SUBN_ADM:
+               printf(" (%s)", get_sa_attr(ntohs(hdr->attr_id)));
+               break;
+       case UMAD_CLASS_CM:
+               printf(" (%s)", get_cm_attr(ntohs(hdr->attr_id)));
+               break;
+       default:
+               break;
+       }
+       printf("\n");
+       printf("Attr modifier..0x%04x\n", ntohl(hdr->attr_mod));
+}
+
+static char * get_rmpp_type(uint8_t rmpp_type)
+{
+       switch (rmpp_type) {
+       case UMAD_RMPP_TYPE_DATA:
+               return "Data";
+       case UMAD_RMPP_TYPE_ACK:
+               return "Ack";
+       case UMAD_RMPP_TYPE_STOP:
+               return "Stop";
+       case UMAD_RMPP_TYPE_ABORT:
+               return "Abort";
+       default:
+               return "Unknown";
+       }
+}
+
+static char * get_rmpp_flags(uint8_t rmpp_flags)
+{
+       if (rmpp_flags & UMAD_RMPP_FLAG_ACTIVE)
+               if (rmpp_flags & UMAD_RMPP_FLAG_FIRST)
+                       if (rmpp_flags & UMAD_RMPP_FLAG_LAST)
+                               return "Active - First & Last";
+                       else
+                               return "Active - First";
+               else
+                       if (rmpp_flags & UMAD_RMPP_FLAG_LAST)
+                               return "Active - Last";
+                       else
+                               return "Active";
+       else
+               return "Inactive";
+}
+
+static void print_rmpp_hdr(struct umad_rmpp_hdr *rmpp_hdr)
+{
+       printf("RMPP version...0x%01x\n", rmpp_hdr->rmpp_version);
+       printf("RMPP type......0x%01x (%s)\n", rmpp_hdr->rmpp_type,
+              get_rmpp_type(rmpp_hdr->rmpp_type));
+       printf("RMPP RRespTime.0x%01x\n",
+              rmpp_hdr->rmpp_rtime_flags >> UMAD_RMPP_RESP_TIME_SHIFT);
+       printf("RMPP flags.....0x%01x (%s)\n",
+              rmpp_hdr->rmpp_rtime_flags & UMAD_RMPP_FLAG_MASK,
+              get_rmpp_flags(rmpp_hdr->rmpp_rtime_flags & 
UMAD_RMPP_FLAG_MASK));
+       printf("RMPP status....0x%01x\n", rmpp_hdr->rmpp_status);
+       printf("Seg number.....0x%04x\n", ntohl(rmpp_hdr->seg_num));
+       switch (rmpp_hdr->rmpp_type) {
+       case UMAD_RMPP_TYPE_DATA:
+               printf("Payload len....0x%04x\n",
+                      ntohl(rmpp_hdr->paylen_newwin));
+               break;
+       case UMAD_RMPP_TYPE_ACK:
+               printf("New window.....0x%04x\n",
+                      ntohl(rmpp_hdr->paylen_newwin));
+               break;
+       default:
+               printf("Data 2.........0x%04x\n",
+                      ntohl(rmpp_hdr->paylen_newwin));
+               break;
+       }
+}
+
+static char * get_smp_attr(uint16_t attr)
+{
+       switch (attr) {
+       case UMAD_ATTR_NOTICE:
+               return "notice";
+       case UMAD_SMP_ATTR_NODE_DESC:
+               return "node description";
+       case UMAD_SMP_ATTR_NODE_INFO:
+               return "node info";
+       case UMAD_SMP_ATTR_SWITCH_INFO:
+               return "switch info";
+       case UMAD_SMP_ATTR_GUID_INFO:
+               return "GUID info";
+       case UMAD_SMP_ATTR_PORT_INFO:
+               return "port info";
+       case UMAD_SMP_ATTR_PKEY_TABLE:
+               return "pkey table";
+       case UMAD_SMP_ATTR_SLVL_TABLE:
+               return "SL to VL table";
+       case UMAD_SMP_ATTR_VL_ARB_TABLE:
+               return "VL arbitration table";
+       case UMAD_SMP_ATTR_LINEAR_FT:
+               return "linear forwarding table";
+       case UMAD_SMP_ATTR_RANDOM_FT:
+               return "random forward table";
+       case UMAD_SMP_ATTR_MCAST_FT:
+               return "multicast forward table";
+       case UMAD_SMP_ATTR_SM_INFO:
+               return "SM info";
+       case UMAD_SMP_ATTR_VENDOR_DIAG:
+               return "vendor diags";
+       case UMAD_SMP_ATTR_LED_INFO:
+               return "LED info";
+       default:
+               return "Unknown";
+       }
+}
+
+static void print_data(char *msg, uint8_t *data, int size)
+{
+       int i;
+
+       for (i = 0; i < size; i++) {
+               if (i % 16 == 0)
+                       printf("%s", msg);
+               printf("%.2x ", data[i]);
+               if ((i < size - 1) && (i % 16 == 15))
+                       printf("\n");
+       }
+       printf("\n");
+}
+
+static void print_smp(struct umad_smp *smp)
+{
+       printf("MAD version....0x%01x\n", smp->base_version);
+       printf("Class..........0x%01x (%s)\n", smp->mgmt_class,
+              get_class_name(smp->mgmt_class));
+       printf("Class version..0x%01x\n", smp->class_version);
+       printf("Method.........0x%01x (%s)\n", smp->method,
+              get_method_name(smp->mgmt_class, smp->method));
+       printf("Status.........0x%02x\n", ntohs(smp->status));
+       if (smp->status)
+               print_status_details(ntohs(smp->status));
+       printf("Hop pointer...0x%01x\n", smp->hop_ptr);
+       printf("Hop counter...0x%01x\n", smp->hop_cnt);
+       printf("Trans ID.......0x%llx\n", (unsigned long long) 
ntohll(smp->tid));
+       printf("Attr ID........0x%02x (%s)\n", ntohs(smp->attr_id),
+               get_smp_attr(ntohs(smp->attr_id)));
+       printf("Attr modifier..0x%04x\n", ntohl(smp->attr_mod));
+
+       printf("Mkey...........0x%llx\n",
+              (unsigned long long) ntohll(*(uint64_t *) smp->mkey));
+       printf("DR SLID........0x%02x\n", ntohs(smp->dr_slid));
+       printf("DR DLID........0x%02x\n", ntohs(smp->dr_dlid));
+
+       if (verbose) {
+               print_data("SMP data.......", smp->data, UMAD_LEN_SMP_DATA);
+               print_data("Initial path...", smp->initial_path,
+                          UMAD_SMP_MAX_HOPS);
+               print_data("Return path....", smp->return_path,
+                          UMAD_SMP_MAX_HOPS);
+       }
+}
+
+static void print_sa_hdr(struct umad_sa_packet *mad)
+{
+       printf("SM key.........0x%llx\n",
+              (unsigned long long) ntohll(*(uint64_t *) mad->sm_key));
+       printf("Attr offset....0x%02x\n", ntohs(mad->attr_offset));
+       printf("Comp mask......0x%llx\n",
+              (unsigned long long) ntohll(mad->comp_mask));
+}
+
+static int is_rmpp_mad(uint8_t mgmt_class)
+{
+       return ((mgmt_class == UMAD_CLASS_SUBN_ADM) ||
+               ((mgmt_class >= UMAD_CLASS_VENDOR_RANGE2_START) &&
+                (mgmt_class <= UMAD_CLASS_VENDOR_RANGE2_END)) ||
+               (mgmt_class == UMAD_CLASS_DEVICE_MGMT) ||
+               (mgmt_class == UMAD_CLASS_DEVICE_ADM) ||
+               (mgmt_class == UMAD_CLASS_BIS));
+}
+
+static void print_gmp(struct umad_hdr *hdr)
+{
+       print_mad_hdr(hdr);
+
+       if (is_rmpp_mad(hdr->mgmt_class))
+               print_rmpp_hdr(&((struct umad_rmpp_packet *) hdr)->rmpp_hdr);
+
+       if (!verbose)
+               return;
+
+       if (hdr->mgmt_class == UMAD_CLASS_SUBN_ADM) {
+               struct umad_sa_packet *sa_mad = (struct umad_sa_packet *) hdr;
+               print_sa_hdr(sa_mad);
+               print_data("SA data........", sa_mad->data,
+                          UMAD_LEN_SA_DATA);
+       } else if ((hdr->mgmt_class >= UMAD_CLASS_VENDOR_RANGE2_START) &&
+                  (hdr->mgmt_class <= UMAD_CLASS_VENDOR_RANGE2_END)) {
+               struct umad_vendor_packet *vendor_mad = (struct 
umad_vendor_packet *) hdr;
+               printf("Vendor OUI......%01x %01x %01x\n",
+                       vendor_mad->oui[0],
+                       vendor_mad->oui[1],
+                       vendor_mad->oui[2]);
+               print_data("Vendor data....", vendor_mad->data,
+                          UMAD_LEN_VENDOR_DATA);
+       } else if (is_rmpp_mad(hdr->mgmt_class)) {
+               print_data("RMPP data....", ((struct umad_rmpp_packet *) 
hdr)->data,
+                          UMAD_LEN_RMPP_DATA);
+       } else {
+               print_data("MAD data.......", ((struct umad_packet *) 
hdr)->data, UMAD_LEN_DATA);
+       }
+}
+
+static void print_mad(struct mad_info *umad)
+{
+       struct umad_hdr *hdr;
+
+       umad_addr_dump(&umad->user_mad.addr);
+       hdr = (struct umad_hdr *) umad->data;
+
+       if (hdr->mgmt_class == UMAD_CLASS_SUBN_LID_ROUTED ||
+           hdr->mgmt_class == UMAD_CLASS_SUBN_DIRECTED_ROUTE)
+               print_smp((struct umad_smp *) hdr);
+       else
+               print_gmp(hdr);
+}
+
+static int run(void)
+{
+       int port_id, agent;
+       struct mad_info umad;
+       int ret, len;
+
+       port_id = umad_open_port(ca, port);
+       if (port_id < 0) {
+               printf("umad_open_port %s\n", strerror(-port_id));
+               return 1;
+       }
+
+       agent = umad_register_snoop(port_id, &filter, sizeof filter);
+       if (agent < 0) {
+               printf("umad_register_snoop %s\n", strerror(-agent));
+               ret = -agent;
+               goto close;
+       }
+
+       while (1) {
+               len = sizeof umad;
+               ret = umad_recv(port_id, &umad, &len, -1);
+               if (ret < 0) {
+                       printf("umad_recv %s\n", strerror(-ret));
+                       break;
+               }
+
+               print_mad(&umad);
+       }
+
+       umad_unregister(port_id, agent);
+close:
+       umad_close_port(port_id);
+       return ret;
+}
+
+static void show_usage(char *name)
+{
+       printf("Usage: %s        capture and display IB MAD traffic\n\n", name);
+       printf("Options:\n");
+       printf("  -C, --Ca=<ca_name>\n");
+       printf("  -P, --Port=<port_number>\n");
+       printf("  -c, --class=<management_class>\n");
+       printf("  -n, --class_version=<class_version>\n");
+       printf("  -a, --attr=<attribute_id>\n");
+       printf("  -e, --errors        (capture only MADs which complete in 
error)\n");
+       printf("  -o, --oui=<oui>\n");
+       printf("  -h, --help\n");
+       printf("  -v, --verbose       (display MAD data)\n");
+}
+
+int main(int argc, char *argv[])
+{
+       int val;
+
+       while (1) {
+               int c;
+               static struct option long_options[] = {
+                       {.name = "Ca",      .has_arg = 1, .val = 'C'},
+                       {.name = "Port",    .has_arg = 1, .val = 'P'},
+                       {.name = "class",   .has_arg = 1, .val = 'c'},
+                       {.name = "class_version", .has_arg = 1, .val = 'n'},
+                       {.name = "attr",    .has_arg = 1, .val = 'a'},
+                       {.name = "errors",  .has_arg = 0, .val = 'e'},
+                       {.name = "oui",     .has_arg = 1, .val = 'o'},
+                       {.name = "help",    .has_arg = 0, .val = 'h'},
+                       {.name = "verbose", .has_arg = 0, .val = 'v'},
+                       {0, 0, 0, 0}
+               };
+
+               c = getopt_long(argc, argv, "C:P:c:n:a:eo:hv", long_options, 
NULL);
+               if (c == -1)
+                       break;
+
+               switch (c) {
+               case 'C':
+                       ca = optarg;
+                       break;
+               case 'P':
+                       port = (uint8_t) strtoul(optarg, 0, 0);
+                       break;
+               case 'c':
+                       filter.mgmt_class = (uint8_t) strtoul(optarg, 0, 0);
+                       break;
+               case 'n':
+                       filter.mgmt_version = (uint8_t) strtoul(optarg, 0, 0);
+                       break;
+               case 'a':
+                       filter.attr_id = (uint16_t) strtoul(optarg, 0, 0);
+                       break;
+               case 'e':
+                       filter.errors = 1;
+               case 'o':
+                       val = strtoul(optarg, 0, 0);
+                       filter.oui[0] = (uint8_t) (val >> 16);
+                       filter.oui[1] = (uint8_t) (val >> 8);
+                       filter.oui[2] = (uint8_t) val;
+                       break;
+               case 'v':
+                       verbose = 1;
+                       break;
+               default:
+                       show_usage(argv[0]);
+                       exit(1);
+               }
+       }
+
+       val = run();
+       return val;
+}


--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to