Index: openib/src/userspace/management/diags/src/ib_sa_query.c
===================================================================
--- openib/src/userspace/management/diags/src/ib_sa_query.c	(revision 0)
+++ openib/src/userspace/management/diags/src/ib_sa_query.c	(revision 0)
@@ -0,0 +1,443 @@
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <assert.h>
+
+#define _GNU_SOURCE
+#include <getopt.h>
+
+
+#include <infiniband/opensm/osm_log.h>
+#include <infiniband/vendor/osm_vendor_api.h>
+#include <infiniband/vendor/osm_vendor_sa_api.h>
+#include <infiniband/opensm/osm_mad_pool.h>
+
+static char *argv0 = "ib_sa_query";
+
+/**
+ * Declare some globals because I don't want this to be too complex.
+ */
+#define MAX_PORTS (8)
+osmv_query_res_t   result;
+osm_log_t          log_osm;
+osm_mad_pool_t     mad_pool;
+osm_vendor_t      *vendor = NULL;
+int                osm_debug = 0;
+
+enum
+{
+        ALL,
+        LID_ONLY,
+        GUID_ONLY,
+} node_print_desc = ALL;
+
+char              *requested_name = NULL;
+ib_net16_t         query_type = IB_MAD_ATTR_NODE_RECORD;
+
+/**
+ * Call back for the node record request.
+ */
+void
+query_res_cb(osmv_query_res_t *res)
+{
+        result = *res;
+}
+
+void
+print_node_record(ib_node_record_t *node_record)
+{
+        ib_node_info_t *p_ni = NULL;
+        p_ni = &(node_record->node_info);
+        
+        switch (node_print_desc)
+        {
+                case LID_ONLY:
+                        printf("%d\n", cl_ntoh16(node_record->lid));
+                        return;
+                case GUID_ONLY:
+                        printf("0x%016" PRIx64 "\n", cl_ntoh64(p_ni->port_guid));
+                        return;
+                case ALL: break;
+                default: break;
+        }
+        printf("NodeRecord dump:\n"
+                "\t\t\t\tRID\n"
+                "\t\t\t\tLid.....................0x%X\n"
+                "\t\t\t\tReserved................0x%X\n"
+                "\t\t\t\tNodeInfoDump\n"
+                "\t\t\t\tbase_version............0x%X\n"
+                "\t\t\t\tclass_version...........0x%X\n"
+                "\t\t\t\tnode_type...............%s\n"
+                "\t\t\t\tnum_ports...............0x%X\n"
+                "\t\t\t\tsys_guid................0x%016" PRIx64 "\n"
+                "\t\t\t\tnode_guid...............0x%016" PRIx64 "\n"
+                "\t\t\t\tport_guid...............0x%016" PRIx64 "\n"
+                "\t\t\t\tpartition_cap...........0x%X\n"
+                "\t\t\t\tdevice_id...............0x%X\n"
+                "\t\t\t\trevision................0x%X\n"
+                "\t\t\t\tport_num................0x%X\n"
+                "\t\t\t\tvendor_id...............0x%X\n"
+                "\t\t\t\tNodeDescription\n"
+                "\t\t\t\t%s\n"
+                "",
+                cl_ntoh16(node_record->lid),
+                cl_ntoh16(node_record->resv),
+                p_ni->base_version,
+                p_ni->class_version,
+                ib_get_node_type_str( p_ni->node_type ),
+                p_ni->num_ports,
+                cl_ntoh64( p_ni->sys_guid ),
+                cl_ntoh64( p_ni->node_guid ),
+                cl_ntoh64( p_ni->port_guid ),
+                cl_ntoh16( p_ni->partition_cap ),
+                cl_ntoh16( p_ni->device_id ),
+                cl_ntoh32( p_ni->revision ),
+                ib_node_info_get_local_port_num( p_ni ),
+                cl_ntoh32( ib_node_info_get_vendor_id( p_ni )),
+                node_record->node_desc.description
+                );
+}
+
+void
+print_path_record(ib_path_rec_t *p_pr)
+{
+        printf("PathRecord dump:\n"
+                 "\t\t\t\tresv0...................0x%016" PRIx64 "\n"
+                 "\t\t\t\tdgid....................0x%016" PRIx64 " : "
+                 "0x%016" PRIx64 "\n"
+                 "\t\t\t\tsgid....................0x%016" PRIx64 " : "
+                 "0x%016" PRIx64 "\n"
+                 "\t\t\t\tdlid....................0x%X\n"
+                 "\t\t\t\tslid....................0x%X\n"
+                 "\t\t\t\thop_flow_raw............0x%X\n"
+                 "\t\t\t\ttclass..................0x%X\n"
+                 "\t\t\t\tnum_path_revers.........0x%X\n"
+                 "\t\t\t\tpkey....................0x%X\n"
+                 "\t\t\t\tsl......................0x%X\n"
+                 "\t\t\t\tmtu.....................0x%X\n"
+                 "\t\t\t\trate....................0x%X\n"
+                 "\t\t\t\tpkt_life................0x%X\n"
+                 "\t\t\t\tpreference..............0x%X\n"
+                 "\t\t\t\tresv2...................0x%X\n"
+                 "\t\t\t\tresv3...................0x%X\n"
+                 "",
+                 *(uint64_t*)p_pr->resv0,
+                 cl_ntoh64( p_pr->dgid.unicast.prefix ),
+                 cl_ntoh64( p_pr->dgid.unicast.interface_id ),
+                 cl_ntoh64( p_pr->sgid.unicast.prefix ),
+                 cl_ntoh64( p_pr->sgid.unicast.interface_id ),
+                 cl_ntoh16( p_pr->dlid ),
+                 cl_ntoh16( p_pr->slid ),
+                 cl_ntoh32( p_pr->hop_flow_raw ),
+                 p_pr->tclass,
+                 p_pr->num_path,
+                 cl_ntoh16( p_pr->pkey ),
+                 cl_ntoh16( p_pr->sl ),
+                 p_pr->mtu,
+                 p_pr->rate,
+                 p_pr->pkt_life,
+                 p_pr->preference,
+                 *(uint32_t*)&p_pr->resv2,
+                 *((uint16_t*)&p_pr->resv2 + 2)
+                 );
+}
+
+static void
+return_mad(void)
+{
+        /*
+         * Return the IB query MAD to the pool as necessary.
+         */
+        if( result.p_result_madw != NULL )
+        {
+                osm_mad_pool_put( &mad_pool, result.p_result_madw );
+                result.p_result_madw = NULL;
+        }
+}
+
+/**
+ * Attempt invalid query's to break the interface like I saw before.
+ */
+static void
+break_get_all_records(osm_bind_handle_t bind_handle)
+{
+        int               i = 0, j = 0;
+        ib_api_status_t   status;
+        osmv_query_req_t  req;
+        osmv_user_query_t user;
+
+        for (i = 0; i < 5000; i++)
+        {
+                for (j = 0; j < 20; j += 50)
+                {
+                        cl_memclr( &req, sizeof( req ) );
+                        cl_memclr( &user, sizeof( user ) );
+                        
+                        user.attr_id = j;
+                        user.attr_offset = i;
+                        
+                        req.query_type = OSMV_QUERY_USER_DEFINED;
+                        req.timeout_ms = 100;
+                        req.retry_cnt = 1;
+                        req.flags = OSM_SA_FLAGS_SYNC;
+                        req.query_context = NULL;
+                        req.pfn_query_cb = query_res_cb;
+                        req.p_query_input = &user;
+                        req.sm_key = 0;
+                        
+                        if ((status = osmv_query_sa(bind_handle, &req)) != IB_SUCCESS)
+                        {
+                                fprintf(stderr, "Query SA failed: %s\n",
+                                        ib_get_err_str(status));
+                        }
+                        if (result.status != IB_SUCCESS)
+                        {
+                                fprintf(stderr, "Query result returned: %s\n",
+                                        ib_get_err_str(result.status));
+                        }
+                        return_mad();
+                }
+        }
+}
+
+/**
+ * Get the node records available.
+ */
+static ib_api_status_t
+get_all_records(osm_bind_handle_t bind_handle,
+                ib_net16_t query_id,
+                ib_net16_t attr_offset)
+{
+        ib_api_status_t   status;
+        osmv_query_req_t  req;
+        osmv_user_query_t user;
+
+        cl_memclr( &req, sizeof( req ) );
+        cl_memclr( &user, sizeof( user ) );
+
+        user.attr_id = query_id;
+        user.attr_offset = attr_offset;
+
+        req.query_type = OSMV_QUERY_USER_DEFINED;
+        req.timeout_ms = 100;
+        req.retry_cnt = 1;
+        req.flags = OSM_SA_FLAGS_SYNC;
+        req.query_context = NULL;
+        req.pfn_query_cb = query_res_cb;
+        req.p_query_input = &user;
+        req.sm_key = 0;
+
+        if ((status = osmv_query_sa(bind_handle, &req)) != IB_SUCCESS)
+        {
+                fprintf(stderr, "Query SA failed: %s\n",
+                        ib_get_err_str(status));
+                return (status);
+        }
+
+        if (result.status != IB_SUCCESS)
+        {
+                fprintf(stderr, "Query result returned: %s\n",
+                        ib_get_err_str(result.status));
+                return (result.status);
+        }
+        return (status);
+}
+
+static ib_api_status_t
+print_node_records(osm_bind_handle_t bind_handle)
+{
+        int               i = 0;
+        ib_node_record_t *node_record = NULL;
+        ib_net16_t        attr_offset = ib_get_attr_offset(sizeof(*node_record));
+        ib_api_status_t   status = get_all_records(bind_handle,
+                                                   IB_MAD_ATTR_NODE_RECORD,
+                                                   attr_offset);
+        if (status != IB_SUCCESS)
+        {
+                return (status);
+        }
+
+        for (i = 0; i < result.result_cnt; i++)
+        {
+                node_record = osmv_get_query_node_rec(result.p_result_madw, i);
+                if (!requested_name ||
+                      (strcmp(requested_name,
+                              node_record->node_desc.description) == 0))
+                {
+                        print_node_record(node_record);
+                }
+        }
+        return_mad();
+        return (status);
+}
+
+static ib_api_status_t
+print_path_records(osm_bind_handle_t bind_handle)
+{
+        int               i = 0;
+        ib_path_rec_t    *path_record = NULL;
+        ib_net16_t        attr_offset = ib_get_attr_offset(sizeof(*path_record));
+        ib_api_status_t   status = get_all_records(bind_handle,
+                                                   IB_MAD_ATTR_PATH_RECORD,
+                                                   attr_offset);
+        if (status != IB_SUCCESS)
+        {
+                return (status);
+        }
+
+        for (i = 0; i < result.result_cnt; i++)
+        {
+                path_record = osmv_get_query_path_rec(result.p_result_madw, i);
+                print_path_record(path_record);
+        }
+        return_mad();
+        return (status);
+}
+
+static osm_bind_handle_t
+get_bind_handle(void)
+{
+        uint32_t           i = 0;
+        uint64_t           port_guid = (uint64_t)-1;
+        osm_bind_handle_t  bind_handle;
+        ib_api_status_t    status;
+        ib_port_attr_t     attr_array[MAX_PORTS];
+        uint32_t           num_ports = MAX_PORTS;
+
+        osm_log_construct(&log_osm);
+        if ((status = osm_log_init( &log_osm, TRUE,
+                         0x0001, NULL, TRUE )) != IB_SUCCESS)
+        {
+                fprintf(stderr, "Failed to init osm_log: %s\n",
+                        ib_get_err_str(status));
+                exit (-1);
+        }
+        osm_log_set_level(&log_osm, OSM_LOG_NONE);
+        if (osm_debug)
+        {
+                osm_log_set_level(&log_osm, OSM_LOG_DEFAULT_LEVEL);
+        }
+
+        vendor = osm_vendor_new(&log_osm, 100);
+        osm_mad_pool_construct(&mad_pool);
+        if ((status = osm_mad_pool_init(&mad_pool, &log_osm)) != IB_SUCCESS)
+        {
+                fprintf(stderr, "Failed to init mad pool: %s\n",
+                        ib_get_err_str(status));
+                exit (-1);
+        }
+
+        if ((status = osm_vendor_get_all_port_attr(vendor, attr_array, &num_ports)) != IB_SUCCESS)
+        {
+                fprintf(stderr, "Failed to get port attributes: %s\n",
+                        ib_get_err_str(status));
+                exit (-1);
+        }
+
+        for (i = 0; i < num_ports; i++)
+        {
+                if (attr_array[i].link_state == IB_LINK_ACTIVE)
+                {
+                        port_guid = attr_array[i].port_guid;
+                }
+        }
+        if (port_guid == (uint64_t)-1)
+        {
+                fprintf(stderr, "Failed to find active port, check port status with \"ibstat\"\n");
+                exit (-1);
+        }
+
+        bind_handle = osmv_bind_sa(vendor, &mad_pool, port_guid);
+
+        if (bind_handle == OSM_BIND_INVALID_HANDLE)
+        {
+                fprintf(stderr, "Failed to bind to SA\n");
+                exit(-1);
+        }
+        return (bind_handle);
+}
+
+
+static void
+clean_up(void)
+{
+        osm_mad_pool_destroy(&mad_pool);
+        osm_vendor_delete(&vendor);
+}
+
+void
+usage(void)
+{
+	fprintf(stderr, "Usage: %s [-h -d -P -L -G][<name>]\n", argv0);
+	fprintf(stderr, "   Query's node records by default\n");
+	fprintf(stderr, "   -d enable osm debugging\n");
+	fprintf(stderr, "   -P get Pathrecord info\n");
+	fprintf(stderr, "   -L Return just the Lid of the name specified\n");
+	fprintf(stderr, "   -G Return just the Guid of the name specified\n");
+	exit(-1);
+}
+
+int
+main(int argc, char **argv)
+{
+        int                ch = 0;
+        int                break_mode = 0;
+        osm_bind_handle_t  bind_handle;
+
+        static char const str_opts[] = "PLGdbh";
+        static const struct option long_opts [] = {
+           {"P", 0, 0, 'P'},
+           {"L", 0, 0, 'L'},
+           {"G", 0, 0, 'G'},
+           {"d", 0, 0, 'd'},
+           {"b", 0, 0, 'b'},
+           {"help", 0, 0, 'h'},
+           { }
+        };
+
+	argv0 = argv[0];
+
+        while ((ch = getopt_long(argc, argv, str_opts, long_opts, NULL))
+                != -1)
+        {
+                switch (ch)
+                {
+                        case 'P': query_type = IB_MAD_ATTR_PATH_RECORD; break;
+                        case 'L': node_print_desc = LID_ONLY; break;
+                        case 'G': node_print_desc = GUID_ONLY; break;
+                        case 'd': osm_debug = 1; break;
+                        case 'b': break_mode = 1; break;
+                        case 'h':
+                        default:
+                        	usage();
+                }
+	}
+	argc -= optind;
+	argv += optind;
+
+        if (argc)
+        {
+                requested_name = argv[0];
+        }
+
+        bind_handle = get_bind_handle();
+        if (break_mode)
+        {
+                break_get_all_records(bind_handle);
+                goto cleanup;
+        }
+        switch (query_type)
+        {
+                case IB_MAD_ATTR_NODE_RECORD:
+                        print_node_records(bind_handle);
+                        break;
+                case IB_MAD_ATTR_PATH_RECORD:
+                        print_path_records(bind_handle);
+                        break;
+        }
+
+cleanup:
+        clean_up();
+        return (0);
+}
+
Index: openib/src/userspace/management/diags/Makefile.am
===================================================================
--- openib/src/userspace/management/diags/Makefile.am	(revision 56)
+++ openib/src/userspace/management/diags/Makefile.am	(working copy)
@@ -6,7 +6,8 @@
 
 bin_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/perfquery src/sminfo src/smpdump src/smpquery \
+			 src/ib_sa_query
 
 bin_SCRIPTS = scripts/ibcheckerrs scripts/ibchecknet scripts/ibchecknode \
               scripts/ibcheckport scripts/ibhosts scripts/ibstatus \
@@ -99,6 +100,15 @@
 		     $(libdir)/libibmad.la
 src_smpquery_LDFLAGS = -Wl,--rpath -Wl,$(libdir)
 
+src_ib_sa_query_SOURCES = src/ib_sa_query.c
+src_ib_sa_query_CFLAGS = -Wall
+src_ib_sa_query_LDADD = $(libdir)/libibmad.la \
+		     $(libdir)/libosmvendor.la \
+		     $(libdir)/libopensm.la \
+		     $(libdir)/libosmcomp.la
+src_ib_sa_query_LDFLAGS = -Wl,--rpath -Wl,$(libdir)
+
+
 EXTRA_DIST = scripts diags.spec.in
 
 dist-hook: diags.spec
