]> git.openfabrics.org - ~shefty/rdma-win.git/commitdiff
update ib-mgmt_class_vers
authorSean Hefty <sean.hefty@intel.com>
Tue, 8 Jun 2010 23:50:01 +0000 (23:50 +0000)
committerSean Hefty <sean.hefty@intel.com>
Tue, 8 Jun 2010 23:50:01 +0000 (23:50 +0000)
Update libibmad, libibnetdisc, and ib-diags to the management.git tree commit 4a55423059e76ccba95aed36dd256510082b1e27

Signed-off-by: Sean Hefty <sean.hefty@intel.com>
git-svn-id: svn://openib.tc.cornell.edu/gen1@2822 ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86

55 files changed:
trunk/core/al/kernel/al_cm_cep.c
trunk/core/al/kernel/al_ioc_pnp.c
trunk/inc/iba/ib_types.h
trunk/tools/infiniband-diags/include/ibdiag_common.h
trunk/tools/infiniband-diags/src/ibaddr.c
trunk/tools/infiniband-diags/src/ibdiag_common.c
trunk/tools/infiniband-diags/src/iblinkinfo.c
trunk/tools/infiniband-diags/src/ibnetdiscover.c
trunk/tools/infiniband-diags/src/ibping.c
trunk/tools/infiniband-diags/src/ibportstate.c
trunk/tools/infiniband-diags/src/ibqueryerrors.c
trunk/tools/infiniband-diags/src/ibqueryerrors/SOURCES
trunk/tools/infiniband-diags/src/ibroute.c
trunk/tools/infiniband-diags/src/ibsendtrap.c
trunk/tools/infiniband-diags/src/ibstat.c
trunk/tools/infiniband-diags/src/ibsysstat.c
trunk/tools/infiniband-diags/src/ibtracert.c
trunk/tools/infiniband-diags/src/mcm_rereg_test.c
trunk/tools/infiniband-diags/src/perfquery.c
trunk/tools/infiniband-diags/src/saquery.c
trunk/tools/infiniband-diags/src/sminfo.c
trunk/tools/infiniband-diags/src/smpdump.c
trunk/tools/infiniband-diags/src/smpquery.c
trunk/tools/infiniband-diags/src/vendstat.c
trunk/ulp/libibmad/include/infiniband/mad.h
trunk/ulp/libibmad/include/infiniband/mad_osd.h
trunk/ulp/libibmad/include/windows/config.h [new file with mode: 0644]
trunk/ulp/libibmad/src/Sources
trunk/ulp/libibmad/src/bm.c
trunk/ulp/libibmad/src/dump.c
trunk/ulp/libibmad/src/fields.c
trunk/ulp/libibmad/src/gs.c
trunk/ulp/libibmad/src/libibmad.map
trunk/ulp/libibmad/src/mad.c
trunk/ulp/libibmad/src/mad_internal.h
trunk/ulp/libibmad/src/portid.c
trunk/ulp/libibmad/src/register.c
trunk/ulp/libibmad/src/resolve.c
trunk/ulp/libibmad/src/rpc.c
trunk/ulp/libibmad/src/sa.c
trunk/ulp/libibmad/src/serv.c
trunk/ulp/libibmad/src/smp.c
trunk/ulp/libibmad/src/vendor.c
trunk/ulp/libibnetdisc/include/infiniband/ibnetdisc.h
trunk/ulp/libibnetdisc/include/windows/config.h [new file with mode: 0644]
trunk/ulp/libibnetdisc/src/Sources
trunk/ulp/libibnetdisc/src/chassis.c
trunk/ulp/libibnetdisc/src/chassis.h
trunk/ulp/libibnetdisc/src/ibnetdisc.c
trunk/ulp/libibnetdisc/src/ibnetdisc_cache.c [new file with mode: 0644]
trunk/ulp/libibnetdisc/src/ibnetdisc_exports.src
trunk/ulp/libibnetdisc/src/internal.h
trunk/ulp/libibnetdisc/src/query_smp.c [new file with mode: 0644]
trunk/ulp/opensm/user/opensm/osm_helper.c
trunk/ulp/srp/kernel/srp_hba.c

index 9a1d138c140253285c609f232e7ec3d7058347bb..6255846d6fed26f5c8ac220be6f8df9491a3fca8 100644 (file)
@@ -27,7 +27,7 @@
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
  * SOFTWARE.\r
  *\r
- * $Id: al_cm_cep.c 2540 2009-11-03 17:23:09Z shefty $\r
+ * $Id$\r
  */\r
 \r
 \r
@@ -5967,8 +5967,7 @@ __format_path(ib_path_rec_t *p_path, req_path_info_t *p_info,
        p_path->rate = conn_req_path_get_pkt_rate(p_info);\r
        p_path->pkt_life = conn_req_path_get_lcl_ack_timeout(p_info);\r
        p_path->preference = 0;\r
-       p_path->resv1 = 0;\r
-       p_path->resv2 = 0;\r
+       memset(p_path->resv2, 0, sizeof(p_path->resv2));\r
 }\r
 \r
 static void\r
index 498a08bf15d86f814f80d3eaf916c5afbbde5331..feb9f55738e964a23872847a2b1a7d89061138ac 100644 (file)
@@ -979,8 +979,7 @@ __get_path(
         * Clear reserved fields in case they were set to prevent undue path\r
         * thrashing.\r
         */\r
-       p_path->rec.resv1 = 0;\r
-       p_path->rec.resv2 = 0;\r
+       memset(p_path->rec.resv2, 0, sizeof(p_path->rec.resv2));\r
 \r
        return p_path;\r
 }\r
index d01bf94b115dc5fef56831b0c8f3f6becb1b3079..28879898c9f22c82edb0fac29a9e0af7e14a1baa 100644 (file)
@@ -2572,8 +2572,7 @@ typedef __declspec(align(8)) struct _ib_path_rec
        uint8_t                                 rate;\r
        uint8_t                                 pkt_life;\r
        uint8_t                                 preference;\r
-       uint16_t                                resv1;\r
-       uint32_t                                resv2;\r
+       uint8_t                                 resv2[6];\r
 \r
 }      PACK_SUFFIX ib_path_rec_t;\r
 #include <complib/cl_packoff.h>\r
@@ -2624,9 +2623,6 @@ typedef __declspec(align(8)) struct _ib_path_rec
 *              Indicates the relative merit of this path versus other path\r
 *              records returned from the SA.  Lower numbers are better.\r
 *\r
-*      resv1\r
-*              Reserved bytes.\r
-*\r
 *      resv2\r
 *              Reserved bytes.\r
 * SEE ALSO\r
@@ -2936,8 +2932,7 @@ ib_path_rec_init_local(
        p_rec->tclass = 0;\r
        p_rec->service_id = 0;\r
 \r
-       p_rec->resv1 = 0;\r
-       p_rec->resv2 = 0;\r
+       memset(p_rec->resv2, 0, sizeof(p_rec->resv2));\r
 }\r
 /*\r
 * PARAMETERS\r
index f2d548f4816ced19980e359b0b9d8ee78ffee195..9b2add727bd6e8edc63e3090acc8c444ca356601 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2006-2007 The Regents of the University of California.
- * Copyright (c) 2004-2008 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2004-2009 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
@@ -50,10 +50,10 @@ extern int ibd_timeout;
 
 #undef DEBUG
 #define DEBUG(fmt, ...) do { \
-       if (ibdebug || ibverbose) IBWARN(fmt, ## __VA_ARGS__); \
+       if (ibdebug) IBDEBUG(fmt, ## __VA_ARGS__); \
 } while (0)
 #define VERBOSE(fmt, ...) do { \
-       if (ibdebug || ibverbose > 1) IBWARN(fmt, ## __VA_ARGS__); \
+       if (ibverbose) IBVERBOSE(fmt, ## __VA_ARGS__); \
 } while (0)
 #define IBERROR(fmt, ...) iberror(__FUNCTION__, fmt, ## __VA_ARGS__)
 
index b5f867a90a1cdae22669c707fcbaa50ed9d2de4a..6e174580a589bd4515fc8d5030a121fb86924c00 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2008 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2004-2009 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
index 3dd12951a82379b82a5c486837b398442d386089..99861f139c1120183f3963b51dd24e0fbd752c73 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2006-2007 The Regents of the University of California.
- * Copyright (c) 2004-2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2004-2009 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
@@ -147,7 +147,7 @@ static int process_opt(int ch, char *optarg)
                break;
        case 'V':
                fprintf(stderr, "%s %s\n", prog_name, get_build_version());
-               exit(2);
+               exit(0);
        case 'e':
                madrpc_show_errors(1);
                break;
index 29c435210e80d1a1025ef86504829783e0fdb3d2..d0c9b1379a3d82a2007837efd3b498971c0da588 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2007 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
  * Copyright (c) 2007 Xsigo Systems Inc.  All rights reserved.
  * Copyright (c) 2008 Lawrence Livermore National Lab.  All rights reserved.
  *
 
 static char *node_name_map_file = NULL;
 static nn_map_t *node_name_map = NULL;
+static char *load_cache_file = NULL;
 
 static uint64_t guid = 0;
 static char *guid_str = NULL;
 static char *dr_path = NULL;
 static int all = 0;
-static int hops = 0;
 
 static int down_links_only = 0;
 static int line_mode = 0;
@@ -69,13 +69,10 @@ static int print_port_guids = 0;
 
 static unsigned int get_max(unsigned int num)
 {
-       unsigned int v = num;   // 32-bit word to find the log base 2 of
-       unsigned r = 0;         // r will be lg(v)
+       unsigned r = 0;         // r will be lg(num)
 
-       while (v >>= 1)         // unroll for more speed...
-       {
+       while (num >>= 1)       // unroll for more speed...
                r++;
-       }
 
        return (1 << r);
 }
@@ -90,26 +87,24 @@ void get_msg(char *width_msg, char *speed_msg, int msg_size, ibnd_port_t * port)
                                     & mad_get_field(port->remoteport->info, 0,
                                                     IB_PORT_LINK_WIDTH_SUPPORTED_F));
        if ((max_width & mad_get_field(port->info, 0,
-                                      IB_PORT_LINK_WIDTH_ACTIVE_F)) == 0) {
+                                      IB_PORT_LINK_WIDTH_ACTIVE_F)) == 0)
                // we are not at the max supported width
                // print what we could be at.
                snprintf(width_msg, msg_size, "Could be %s",
                         mad_dump_val(IB_PORT_LINK_WIDTH_ACTIVE_F,
                                      buf, 64, &max_width));
-       }
 
        max_speed = get_max(mad_get_field(port->info, 0,
                                          IB_PORT_LINK_SPEED_SUPPORTED_F)
                            & mad_get_field(port->remoteport->info, 0,
                                            IB_PORT_LINK_SPEED_SUPPORTED_F));
        if ((max_speed & mad_get_field(port->info, 0,
-                                      IB_PORT_LINK_SPEED_ACTIVE_F)) == 0) {
+                                      IB_PORT_LINK_SPEED_ACTIVE_F)) == 0)
                // we are not at the max supported speed
                // print what we could be at.
                snprintf(speed_msg, msg_size, "Could be %s",
                         mad_dump_val(IB_PORT_LINK_SPEED_ACTIVE_F,
                                      buf, 64, &max_speed));
-       }
 }
 
 void print_port(ibnd_node_t * node, ibnd_port_t * port)
@@ -138,20 +133,34 @@ void print_port(ibnd_node_t * node, ibnd_port_t * port)
        width_msg[0] = '\0';
        speed_msg[0] = '\0';
 
-       n = snprintf(link_str, 256, "(%3s %s %6s/%8s)",
+       /* C14-24.2.1 states that a down port allows for invalid data to be
+        * returned for all PortInfo components except PortState and
+        * PortPhysicalState */
+       if (istate != IB_LINK_DOWN) {
+               n = snprintf(link_str, 256, "(%3s %9s %6s/%8s)",
                     mad_dump_val(IB_PORT_LINK_WIDTH_ACTIVE_F, width, 64,
                                  &iwidth),
                     mad_dump_val(IB_PORT_LINK_SPEED_ACTIVE_F, speed, 64,
-                                 &ispeed), mad_dump_val(IB_PORT_STATE_F, state,
-                                                        64, &istate),
+                                 &ispeed),
+                    mad_dump_val(IB_PORT_STATE_F, state, 64, &istate),
+                    mad_dump_val(IB_PORT_PHYS_STATE_F, physstate, 64,
+                                 &iphystate));
+       } else {
+               n = snprintf(link_str, 256, "(              %6s/%8s)",
+                    mad_dump_val(IB_PORT_STATE_F, state, 64, &istate),
                     mad_dump_val(IB_PORT_PHYS_STATE_F, physstate, 64,
                                  &iphystate));
+       }
 
-       if (add_sw_settings)
-               snprintf(link_str + n, 256 - n, " (HOQ:%d VL_Stall:%d)",
-                        mad_get_field(port->info, 0, IB_PORT_HOQ_LIFE_F),
-                        mad_get_field(port->info, 0,
-                                      IB_PORT_VL_STALL_COUNT_F));
+       /* again default values due to C14-24.2.1 */
+       if (add_sw_settings && istate != IB_LINK_DOWN) {
+               snprintf(link_str + n, 256 - n,
+                       " (HOQ:%d VL_Stall:%d)",
+                       mad_get_field(port->info, 0,
+                               IB_PORT_HOQ_LIFE_F),
+                       mad_get_field(port->info, 0,
+                               IB_PORT_VL_STALL_COUNT_F));
+       }
 
        if (port->remoteport) {
                char *remap =
@@ -231,10 +240,14 @@ void print_switch(ibnd_node_t * node, void *user_data)
 
 static int process_opt(void *context, int ch, char *optarg)
 {
+       struct ibnd_config *cfg = context;
        switch (ch) {
        case 1:
                node_name_map_file = strdup(optarg);
                break;
+       case 2:
+               load_cache_file = strdup(optarg);
+               break;
        case 'S':
                guid_str = optarg;
                guid = (uint64_t) strtoull(guid_str, 0, 0);
@@ -246,7 +259,7 @@ static int process_opt(void *context, int ch, char *optarg)
                all = 1;
                break;
        case 'n':
-               hops = (int)strtol(optarg, NULL, 0);
+               cfg->max_hops = strtoul(optarg, NULL, 0);
                break;
        case 'd':
                down_links_only = 1;
@@ -262,6 +275,9 @@ static int process_opt(void *context, int ch, char *optarg)
                break;
        case 'R':               /* nop */
                break;
+       case 'o':
+               cfg->max_smps = strtoul(optarg, NULL, 0);
+               break;
        default:
                return -1;
        }
@@ -271,6 +287,7 @@ static int process_opt(void *context, int ch, char *optarg)
 
 int main(int argc, char **argv)
 {
+       struct ibnd_config config = { 0 };
        int rc = 0;
        int resolved = -1;
        ibnd_fabric_t *fabric = NULL;
@@ -296,21 +313,23 @@ int main(int argc, char **argv)
                 "print additional switch settings (PktLifeTime, HoqLife, VLStallCount)"},
                {"portguids", 'g', 0, NULL,
                 "print port guids instead of node guids"},
+               {"load-cache", 2, 1, "<file>",
+                "filename of ibnetdiscover cache to load"},
+               {"outstanding_smps", 'o', 1, NULL,
+                "specify the number of outstanding SMP's which should be "
+                "issued during the scan"},
                {"GNDN", 'R', 0, NULL,
                 "(This option is obsolete and does nothing)"},
                {0}
        };
        char usage_args[] = "";
 
-       ibdiag_process_opts(argc, argv, NULL, "SDandlpgRGL", opts, process_opt,
-                           usage_args, NULL);
+       ibdiag_process_opts(argc, argv, &config, "SDandlpgRGL", opts,
+                           process_opt, usage_args, NULL);
 
        argc -= optind;
        argv += optind;
 
-       if (ibverbose)
-               ibnd_debug(1);
-
        ibmad_port = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 3);
        if (!ibmad_port) {
                fprintf(stderr, "Failed to open %s port %d", ibd_ca,
@@ -318,11 +337,18 @@ int main(int argc, char **argv)
                exit(1);
        }
 
-       if (ibd_timeout)
+       if (ibd_timeout) {
                mad_rpc_set_timeout(ibmad_port, ibd_timeout);
+               config.timeout_ms = ibd_timeout;
+       }
 
        node_name_map = open_node_name_map(node_name_map_file);
 
+       if (dr_path && load_cache_file) {
+               fprintf(stderr, "Cannot specify cache and direct route path\n");
+               exit(1);
+       }
+
        if (dr_path) {
                /* only scan part of the fabric */
                if ((resolved =
@@ -339,19 +365,25 @@ int main(int argc, char **argv)
                               guid_str);
        }
 
-       if (resolved >= 0)
-               if ((fabric = ibnd_discover_fabric(ibmad_port, &port_id,
-                                                  hops)) == NULL)
-                       IBWARN
-                           ("Single node discover failed; attempting full scan\n");
-
-       if (!fabric)
-               if ((fabric =
-                    ibnd_discover_fabric(ibmad_port, NULL, -1)) == NULL) {
+       if (load_cache_file) {
+               if ((fabric = ibnd_load_fabric(load_cache_file, 0)) == NULL) {
+                       fprintf(stderr, "loading cached fabric failed\n");
+                       exit(1);
+               }
+       } else {
+               if (resolved >= 0 &&
+                   !(fabric =
+                     ibnd_discover_fabric(ibd_ca, ibd_ca_port, &port_id, &config)))
+                       IBWARN("Single node discover failed;"
+                              " attempting full scan\n");
+
+               if (!fabric &&
+                   !(fabric = ibnd_discover_fabric(ibd_ca, ibd_ca_port, NULL, &config))) {
                        fprintf(stderr, "discover failed\n");
                        rc = 1;
                        goto close_port;
                }
+       }
 
        if (!all && guid_str) {
                ibnd_node_t *sw = ibnd_find_node_guid(fabric, guid);
index ce9affcee5b129ff96564ff4c116c6fad209a8ad..347e7b2daf5a2ba440e8a20f9c05b31313960c1a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2008 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
  * Copyright (c) 2007 Xsigo Systems Inc.  All rights reserved.
  * Copyright (c) 2008 Lawrence Livermore National Lab.  All rights reserved.
  *
@@ -34,7 +34,7 @@
  */
 
 #if HAVE_CONFIG_H
-#  include <config.h>
+#include <config.h>
 #endif                         /* HAVE_CONFIG_H */
 
 #define _GNU_SOURCE
 #define LIST_SWITCH_NODE (1 << IB_NODE_SWITCH)
 #define LIST_ROUTER_NODE (1 << IB_NODE_ROUTER)
 
-struct ibmad_port *srcport;
+#define DIFF_FLAG_SWITCH           0x01
+#define DIFF_FLAG_CA               0x02
+#define DIFF_FLAG_ROUTER           0x04
+#define DIFF_FLAG_PORT_CONNECTION  0x08
+#define DIFF_FLAG_LID              0x10
+#define DIFF_FLAG_NODE_DESCRIPTION 0x20
+
+#define DIFF_FLAG_DEFAULT (DIFF_FLAG_SWITCH | DIFF_FLAG_CA | DIFF_FLAG_ROUTER \
+                          | DIFF_FLAG_PORT_CONNECTION)
 
 static FILE *f;
 
 static char *node_name_map_file = NULL;
 static nn_map_t *node_name_map = NULL;
+static char *cache_file = NULL;
+static char *load_cache_file = NULL;
+static char *diff_cache_file = NULL;
+static unsigned diffcheck_flags = DIFF_FLAG_DEFAULT;
 
 static int report_max_hops = 0;
 
@@ -181,16 +193,18 @@ void list_nodes(ibnd_fabric_t * fabric, int list)
                ibnd_iter_nodes_type(fabric, list_node, IB_NODE_ROUTER, NULL);
 }
 
-void out_ids(ibnd_node_t * node, int group, char *chname)
+void out_ids(ibnd_node_t * node, int group, char *chname, char *out_prefix)
 {
        uint64_t sysimgguid =
            mad_get_field64(node->info, 0, IB_NODE_SYSTEM_GUID_F);
 
-       fprintf(f, "\nvendid=0x%x\ndevid=0x%x\n",
-               mad_get_field(node->info, 0, IB_NODE_VENDORID_F),
+       fprintf(f, "\n%svendid=0x%x\n", out_prefix ? out_prefix : "",
+               mad_get_field(node->info, 0, IB_NODE_VENDORID_F));
+       fprintf(f, "%sdevid=0x%x\n", out_prefix ? out_prefix : "",
                mad_get_field(node->info, 0, IB_NODE_DEVID_F));
        if (sysimgguid)
-               fprintf(f, "sysimgguid=0x%" PRIx64, sysimgguid);
+               fprintf(f, "%ssysimgguid=0x%" PRIx64,
+                       out_prefix ? out_prefix : "", sysimgguid);
        if (group && node->chassis && node->chassis->chassisnum) {
                fprintf(f, "\t\t# Chassis %d", node->chassis->chassisnum);
                if (chname)
@@ -215,14 +229,29 @@ uint64_t out_chassis(ibnd_fabric_t * fabric, unsigned char chassisnum)
        return guid;
 }
 
-void out_switch(ibnd_node_t * node, int group, char *chname)
+void out_switch_detail(ibnd_node_t * node, char *sw_prefix)
+{
+       char *nodename = NULL;
+
+       nodename = remap_node_name(node_name_map, node->guid, node->nodedesc);
+
+       fprintf(f, "%sSwitch\t%d %s\t\t# \"%s\" %s port 0 lid %d lmc %d",
+               sw_prefix ? sw_prefix : "", node->numports, node_name(node),
+               nodename, node->smaenhsp0 ? "enhanced" : "base",
+               node->smalid, node->smalmc);
+
+       free(nodename);
+}
+
+void out_switch(ibnd_node_t * node, int group, char *chname, char *id_prefix,
+               char *sw_prefix)
 {
        char *str;
        char str2[256];
-       char *nodename = NULL;
 
-       out_ids(node, group, chname);
-       fprintf(f, "switchguid=0x%" PRIx64, node->guid);
+       out_ids(node, group, chname, id_prefix);
+       fprintf(f, "%sswitchguid=0x%" PRIx64,
+               id_prefix ? id_prefix : "", node->guid);
        fprintf(f, "(%" PRIx64 ")",
                mad_get_field64(node->info, 0, IB_NODE_PORT_GUID_F));
        if (group) {
@@ -234,42 +263,54 @@ void out_switch(ibnd_node_t * node, int group, char *chname)
                if (str)
                        fprintf(f, "%s", str);
        }
+       fprintf(f, "\n");
 
-       nodename = remap_node_name(node_name_map, node->guid, node->nodedesc);
+       out_switch_detail(node, sw_prefix);
+       fprintf(f, "\n");
+}
 
-       fprintf(f, "\nSwitch\t%d %s\t\t# \"%s\" %s port 0 lid %d lmc %d\n",
-               node->numports, node_name(node), nodename,
-               node->smaenhsp0 ? "enhanced" : "base",
-               node->smalid, node->smalmc);
+void out_ca_detail(ibnd_node_t * node, char *ca_prefix)
+{
+       char *node_type;
 
-       free(nodename);
+       switch (node->type) {
+       case IB_NODE_CA:
+               node_type = "Ca";
+               break;
+       case IB_NODE_ROUTER:
+               node_type = "Rt";
+               break;
+       default:
+               node_type = "???";
+               break;
+       }
+
+       fprintf(f, "%s%s\t%d %s\t\t# \"%s\"", ca_prefix ? ca_prefix : "",
+               node_type, node->numports, node_name(node),
+               clean_nodedesc(node->nodedesc));
 }
 
-void out_ca(ibnd_node_t * node, int group, char *chname)
+void out_ca(ibnd_node_t * node, int group, char *chname, char *id_prefix,
+           char *ca_prefix)
 {
        char *node_type;
-       char *node_type2;
 
-       out_ids(node, group, chname);
+       out_ids(node, group, chname, id_prefix);
        switch (node->type) {
        case IB_NODE_CA:
                node_type = "ca";
-               node_type2 = "Ca";
                break;
        case IB_NODE_ROUTER:
                node_type = "rt";
-               node_type2 = "Rt";
                break;
        default:
                node_type = "???";
-               node_type2 = "???";
                break;
        }
 
-       fprintf(f, "%sguid=0x%" PRIx64 "\n", node_type, node->guid);
-       fprintf(f, "%s\t%d %s\t\t# \"%s\"",
-               node_type2, node->numports, node_name(node),
-               clean_nodedesc(node->nodedesc));
+       fprintf(f, "%s%sguid=0x%" PRIx64 "\n",
+               id_prefix ? id_prefix : "", node_type, node->guid);
+       out_ca_detail(node, ca_prefix);
        if (group && ibnd_is_xsigo_hca(node->guid))
                fprintf(f, " (scp)");
        fprintf(f, "\n");
@@ -289,7 +330,7 @@ static char *out_ext_port(ibnd_port_t * port, int group)
        return (NULL);
 }
 
-void out_switch_port(ibnd_port_t * port, int group)
+void out_switch_port(ibnd_port_t * port, int group, char *out_prefix)
 {
        char *ext_port_str = NULL;
        char *rem_nodename = NULL;
@@ -300,7 +341,7 @@ void out_switch_port(ibnd_port_t * port, int group)
 
        DEBUG("port %p:%d remoteport %p\n", port, port->portnum,
              port->remoteport);
-       fprintf(f, "[%d]", port->portnum);
+       fprintf(f, "%s[%d]", out_prefix ? out_prefix : "", port->portnum);
 
        ext_port_str = out_ext_port(port, group);
        if (ext_port_str)
@@ -332,7 +373,7 @@ void out_switch_port(ibnd_port_t * port, int group)
        free(rem_nodename);
 }
 
-void out_ca_port(ibnd_port_t * port, int group)
+void out_ca_port(ibnd_port_t * port, int group, char *out_prefix)
 {
        char *str = NULL;
        char *rem_nodename = NULL;
@@ -341,7 +382,7 @@ void out_ca_port(ibnd_port_t * port, int group)
        uint32_t ispeed = mad_get_field(port->info, 0,
                                        IB_PORT_LINK_SPEED_ACTIVE_F);
 
-       fprintf(f, "[%d]", port->portnum);
+       fprintf(f, "%s[%d]", out_prefix ? out_prefix : "", port->portnum);
        if (port->node->type != IB_NODE_SWITCH)
                fprintf(f, "(%" PRIx64 ") ", port->guid);
        fprintf(f, "\t%s[%d]",
@@ -384,11 +425,11 @@ static void switch_iter_func(ibnd_node_t * node, void *iter_user_data)
            && node->chassis->chassisnum)
                return;
 
-       out_switch(node, data->group, NULL);
+       out_switch(node, data->group, NULL, NULL, NULL);
        for (p = 1; p <= node->numports; p++) {
                port = node->ports[p];
                if (port && port->remoteport)
-                       out_switch_port(port, data->group);
+                       out_switch_port(port, data->group, NULL);
        }
 }
 
@@ -402,12 +443,12 @@ static void ca_iter_func(ibnd_node_t * node, void *iter_user_data)
        /* Now, skip chassis based CAs */
        if (data->group && node->chassis && node->chassis->chassisnum)
                return;
-       out_ca(node, data->group, NULL);
+       out_ca(node, data->group, NULL, NULL, NULL);
 
        for (p = 1; p <= node->numports; p++) {
                port = node->ports[p];
                if (port && port->remoteport)
-                       out_ca_port(port, data->group);
+                       out_ca_port(port, data->group, NULL);
        }
 }
 
@@ -421,11 +462,11 @@ static void router_iter_func(ibnd_node_t * node, void *iter_user_data)
        /* Now, skip chassis based RTs */
        if (data->group && node->chassis && node->chassis->chassisnum)
                return;
-       out_ca(node, data->group, NULL);
+       out_ca(node, data->group, NULL, NULL, NULL);
        for (p = 1; p <= node->numports; p++) {
                port = node->ports[p];
                if (port && port->remoteport)
-                       out_ca_port(port, data->group);
+                       out_ca_port(port, data->group, NULL);
        }
 }
 
@@ -441,8 +482,9 @@ int dump_topology(int group, ibnd_fabric_t * fabric)
 
        fprintf(f, "#\n# Topology file: generated on %s#\n", ctime(&t));
        if (report_max_hops)
-               fprintf(f, "# Reported max hops discovered: %d\n",
-                       fabric->maxhops_discovered);
+               fprintf(f, "# Reported max hops discovered: %u\n"
+                       "# Total MADs used: %u\n",
+                       fabric->maxhops_discovered, fabric->total_mads_used);
        fprintf(f, "# Initiated from node %016" PRIx64 " port %016" PRIx64 "\n",
                fabric->from_node->guid,
                mad_get_field64(fabric->from_node->info, 0,
@@ -459,19 +501,15 @@ int dump_topology(int group, ibnd_fabric_t * fabric)
                        if (!ch->chassisnum)
                                continue;
                        chguid = out_chassis(fabric, ch->chassisnum);
-
                        chname = NULL;
-/**
- * Will this work for Xsigo?
- */
                        if (ibnd_is_xsigo_guid(chguid)) {
                                for (node = ch->nodes; node;
                                     node = node->next_chassis_node) {
                                        if (ibnd_is_xsigo_hca(node->guid)) {
                                                chname = node->nodedesc;
                                                fprintf(f, "Hostname: %s\n",
-                                                       clean_nodedesc(node->
-                                                                      nodedesc));
+                                                       clean_nodedesc
+                                                       (node->nodedesc));
                                        }
                                }
                        }
@@ -480,7 +518,7 @@ int dump_topology(int group, ibnd_fabric_t * fabric)
                        for (n = 1; n <= SPINES_MAX_NUM; n++) {
                                if (ch->spinenode[n]) {
                                        out_switch(ch->spinenode[n], group,
-                                                  chname);
+                                                  chname, NULL, NULL);
                                        for (p = 1;
                                             p <= ch->spinenode[n]->numports;
                                             p++) {
@@ -488,7 +526,8 @@ int dump_topology(int group, ibnd_fabric_t * fabric)
                                                    ch->spinenode[n]->ports[p];
                                                if (port && port->remoteport)
                                                        out_switch_port(port,
-                                                                       group);
+                                                                       group,
+                                                                       NULL);
                                        }
                                }
                        }
@@ -496,7 +535,7 @@ int dump_topology(int group, ibnd_fabric_t * fabric)
                        for (n = 1; n <= LINES_MAX_NUM; n++) {
                                if (ch->linenode[n]) {
                                        out_switch(ch->linenode[n], group,
-                                                  chname);
+                                                  chname, NULL, NULL);
                                        for (p = 1;
                                             p <= ch->linenode[n]->numports;
                                             p++) {
@@ -504,7 +543,8 @@ int dump_topology(int group, ibnd_fabric_t * fabric)
                                                    ch->linenode[n]->ports[p];
                                                if (port && port->remoteport)
                                                        out_switch_port(port,
-                                                                       group);
+                                                                       group,
+                                                                       NULL);
                                        }
                                }
                        }
@@ -513,12 +553,14 @@ int dump_topology(int group, ibnd_fabric_t * fabric)
                        for (node = ch->nodes; node;
                             node = node->next_chassis_node) {
                                if (node->type == IB_NODE_SWITCH) {
-                                       out_switch(node, group, chname);
+                                       out_switch(node, group, chname, NULL,
+                                                  NULL);
                                        for (p = 1; p <= node->numports; p++) {
                                                port = node->ports[p];
                                                if (port && port->remoteport)
                                                        out_switch_port(port,
-                                                                       group);
+                                                                       group,
+                                                                       NULL);
                                        }
                                }
 
@@ -528,12 +570,12 @@ int dump_topology(int group, ibnd_fabric_t * fabric)
                        for (node = ch->nodes; node;
                             node = node->next_chassis_node) {
                                if (node->type == IB_NODE_CA) {
-                                       out_ca(node, group, chname);
+                                       out_ca(node, group, chname, NULL, NULL);
                                        for (p = 1; p <= node->numports; p++) {
                                                port = node->ports[p];
                                                if (port && port->remoteport)
-                                                       out_ca_port(port,
-                                                                   group);
+                                                       out_ca_port(port, group,
+                                                                   NULL);
                                        }
                                }
                        }
@@ -543,8 +585,8 @@ int dump_topology(int group, ibnd_fabric_t * fabric)
        } else {                /* !group */
                iter_user_data.group = group;
                iter_user_data.skip_chassis_nodes = 0;
-               ibnd_iter_nodes_type(fabric, switch_iter_func,
-                                    IB_NODE_SWITCH, &iter_user_data);
+               ibnd_iter_nodes_type(fabric, switch_iter_func, IB_NODE_SWITCH,
+                                    &iter_user_data);
        }
 
        chname = NULL;
@@ -554,8 +596,8 @@ int dump_topology(int group, ibnd_fabric_t * fabric)
 
                fprintf(f, "\nNon-Chassis Nodes\n");
 
-               ibnd_iter_nodes_type(fabric, switch_iter_func,
-                                    IB_NODE_SWITCH, &iter_user_data);
+               ibnd_iter_nodes_type(fabric, switch_iter_func, IB_NODE_SWITCH,
+                                    &iter_user_data);
        }
 
        iter_user_data.group = group;
@@ -608,16 +650,250 @@ void dump_ports_report(ibnd_node_t * node, void *user_data)
        }
 }
 
+struct iter_diff_data {
+       uint32_t diff_flags;
+       ibnd_fabric_t *fabric1;
+       ibnd_fabric_t *fabric2;
+       char *fabric1_prefix;
+       char *fabric2_prefix;
+       void (*out_header) (ibnd_node_t *, int, char *, char *, char *);
+       void (*out_header_detail) (ibnd_node_t *, char *);
+       void (*out_port) (ibnd_port_t *, int, char *);
+};
+
+static void diff_iter_out_header(ibnd_node_t * node,
+                                struct iter_diff_data *data,
+                                int *out_header_flag)
+{
+       if (!(*out_header_flag)) {
+               (*data->out_header) (node, 0, NULL, NULL, NULL);
+               (*out_header_flag)++;
+       }
+}
+
+static void diff_ports(ibnd_node_t * fabric1_node, ibnd_node_t * fabric2_node,
+                      int *out_header_flag, struct iter_diff_data *data)
+{
+       ibnd_port_t *fabric1_port;
+       ibnd_port_t *fabric2_port;
+       int p;
+
+       for (p = 1; p <= fabric1_node->numports; p++) {
+               int fabric1_out = 0, fabric2_out = 0;
+
+               fabric1_port = fabric1_node->ports[p];
+               fabric2_port = fabric2_node->ports[p];
+
+               if (data->diff_flags & DIFF_FLAG_PORT_CONNECTION) {
+                       if ((fabric1_port && !fabric2_port)
+                           || ((fabric1_port && fabric2_port)
+                               && (fabric1_port->remoteport
+                                   && !fabric2_port->remoteport)))
+                               fabric1_out++;
+                       else if ((!fabric1_port && fabric2_port)
+                                || ((fabric1_port && fabric2_port)
+                                    && (!fabric1_port->remoteport
+                                        && fabric2_port->remoteport)))
+                               fabric2_out++;
+                       else if ((fabric1_port && fabric2_port)
+                                && ((fabric1_port->guid != fabric2_port->guid)
+                                    ||
+                                    ((fabric1_port->remoteport
+                                      && fabric2_port->remoteport)
+                                     && (fabric1_port->remoteport->guid !=
+                                         fabric2_port->remoteport->guid)))) {
+                               fabric1_out++;
+                               fabric2_out++;
+                       }
+               }
+
+               if ((data->diff_flags & DIFF_FLAG_LID)
+                   && fabric1_port && fabric2_port
+                   && fabric1_port->base_lid != fabric2_port->base_lid) {
+                       fabric1_out++;
+                       fabric2_out++;
+               }
+
+               if (fabric1_out) {
+                       diff_iter_out_header(fabric1_node, data,
+                                            out_header_flag);
+                       (*data->out_port) (fabric1_port, 0,
+                                          data->fabric1_prefix);
+               }
+               if (fabric2_out) {
+                       diff_iter_out_header(fabric1_node, data,
+                                            out_header_flag);
+                       (*data->out_port) (fabric2_port, 0,
+                                          data->fabric2_prefix);
+               }
+       }
+}
+
+static void diff_iter_func(ibnd_node_t * fabric1_node, void *iter_user_data)
+{
+       struct iter_diff_data *data = iter_user_data;
+       ibnd_node_t *fabric2_node;
+       ibnd_port_t *fabric1_port;
+       int p;
+
+       DEBUG("DEBUG: fabric1_node %p\n", fabric1_node);
+
+       fabric2_node = ibnd_find_node_guid(data->fabric2, fabric1_node->guid);
+       if (!fabric2_node) {
+               (*data->out_header) (fabric1_node, 0, NULL,
+                                    data->fabric1_prefix,
+                                    data->fabric1_prefix);
+               for (p = 1; p <= fabric1_node->numports; p++) {
+                       fabric1_port = fabric1_node->ports[p];
+                       if (fabric1_port && fabric1_port->remoteport)
+                               (*data->out_port) (fabric1_port, 0,
+                                                  data->fabric1_prefix);
+               }
+       } else if (data->diff_flags &
+                  (DIFF_FLAG_PORT_CONNECTION | DIFF_FLAG_LID
+                   | DIFF_FLAG_NODE_DESCRIPTION)) {
+               int out_header_flag = 0;
+
+               if ((data->diff_flags & DIFF_FLAG_LID
+                    && fabric1_node->smalid != fabric2_node->smalid) ||
+                   (data->diff_flags & DIFF_FLAG_NODE_DESCRIPTION
+                    && memcmp(fabric1_node->nodedesc, fabric2_node->nodedesc,
+                              IB_SMP_DATA_SIZE))) {
+                       (*data->out_header) (fabric1_node, 0, NULL, NULL,
+                                            data->fabric1_prefix);
+                       (*data->out_header_detail) (fabric2_node,
+                                                   data->fabric2_prefix);
+                       fprintf(f, "\n");
+                       out_header_flag++;
+               }
+
+               if (fabric1_node->numports != fabric2_node->numports) {
+                       diff_iter_out_header(fabric1_node, data,
+                                            &out_header_flag);
+                       fprintf(f, "%snumports = %d\n", data->fabric1_prefix,
+                               fabric1_node->numports);
+                       fprintf(f, "%snumports = %d\n", data->fabric2_prefix,
+                               fabric2_node->numports);
+                       return;
+               }
+
+               if (data->diff_flags & DIFF_FLAG_PORT_CONNECTION
+                   || data->diff_flags & DIFF_FLAG_LID)
+                       diff_ports(fabric1_node, fabric2_node, &out_header_flag,
+                                  data);
+       }
+}
+
+static int diff_common(ibnd_fabric_t * orig_fabric, ibnd_fabric_t * new_fabric,
+                      int node_type, uint32_t diff_flags,
+                      void (*out_header) (ibnd_node_t *, int, char *, char *,
+                                          char *),
+                      void (*out_header_detail) (ibnd_node_t *, char *),
+                      void (*out_port) (ibnd_port_t *, int, char *))
+{
+       struct iter_diff_data iter_diff_data;
+
+       iter_diff_data.diff_flags = diff_flags;
+       iter_diff_data.fabric1 = orig_fabric;
+       iter_diff_data.fabric2 = new_fabric;
+       iter_diff_data.fabric1_prefix = "< ";
+       iter_diff_data.fabric2_prefix = "> ";
+       iter_diff_data.out_header = out_header;
+       iter_diff_data.out_header_detail = out_header_detail;
+       iter_diff_data.out_port = out_port;
+       ibnd_iter_nodes_type(orig_fabric, diff_iter_func, node_type,
+                            &iter_diff_data);
+
+       /* Do opposite diff to find existence of node types
+        * in new_fabric but not in orig_fabric.
+        *
+        * In this diff, we don't need to check port connections,
+        * lids, or node descriptions since it has already been
+        * done (i.e. checks are only done when guid exists on both
+        * orig and new).
+        */
+       iter_diff_data.diff_flags = diff_flags & ~DIFF_FLAG_PORT_CONNECTION;
+       iter_diff_data.diff_flags &= ~DIFF_FLAG_LID;
+       iter_diff_data.diff_flags &= ~DIFF_FLAG_NODE_DESCRIPTION;
+       iter_diff_data.fabric1 = new_fabric;
+       iter_diff_data.fabric2 = orig_fabric;
+       iter_diff_data.fabric1_prefix = "> ";
+       iter_diff_data.fabric2_prefix = "< ";
+       iter_diff_data.out_header = out_header;
+       iter_diff_data.out_header_detail = out_header_detail;
+       iter_diff_data.out_port = out_port;
+       ibnd_iter_nodes_type(new_fabric, diff_iter_func, node_type,
+                            &iter_diff_data);
+
+       return 0;
+}
+
+int diff(ibnd_fabric_t * orig_fabric, ibnd_fabric_t * new_fabric)
+{
+       if (diffcheck_flags & DIFF_FLAG_SWITCH)
+               diff_common(orig_fabric, new_fabric, IB_NODE_SWITCH,
+                           diffcheck_flags, out_switch, out_switch_detail,
+                           out_switch_port);
+
+       if (diffcheck_flags & DIFF_FLAG_CA)
+               diff_common(orig_fabric, new_fabric, IB_NODE_CA,
+                           diffcheck_flags, out_ca, out_ca_detail,
+                           out_ca_port);
+
+       if (diffcheck_flags & DIFF_FLAG_ROUTER)
+               diff_common(orig_fabric, new_fabric, IB_NODE_ROUTER,
+                           diffcheck_flags, out_ca, out_ca_detail,
+                           out_ca_port);
+
+       return 0;
+}
+
 static int list, group, ports_report;
 
 static int process_opt(void *context, int ch, char *optarg)
 {
+       struct ibnd_config *cfg = context;
+       char *p;
+
        switch (ch) {
        case 1:
                node_name_map_file = strdup(optarg);
                break;
+       case 2:
+               cache_file = strdup(optarg);
+               break;
+       case 3:
+               load_cache_file = strdup(optarg);
+               break;
+       case 4:
+               diff_cache_file = strdup(optarg);
+               break;
+       case 5:
+               diffcheck_flags = 0;
+               p = strtok(optarg, ",");
+               while (p) {
+                       if (!strcasecmp(p, "sw"))
+                               diffcheck_flags |= DIFF_FLAG_SWITCH;
+                       else if (!strcasecmp(p, "ca"))
+                               diffcheck_flags |= DIFF_FLAG_CA;
+                       else if (!strcasecmp(p, "router"))
+                               diffcheck_flags |= DIFF_FLAG_ROUTER;
+                       else if (!strcasecmp(p, "port"))
+                               diffcheck_flags |= DIFF_FLAG_PORT_CONNECTION;
+                       else if (!strcasecmp(p, "lid"))
+                               diffcheck_flags |= DIFF_FLAG_LID;
+                       else if (!strcasecmp(p, "nodedesc"))
+                               diffcheck_flags |= DIFF_FLAG_NODE_DESCRIPTION;
+                       else {
+                               fprintf(stderr, "invalid diff check key: %s\n",
+                                       p);
+                               return -1;
+                       }
+                       p = strtok(NULL, ",");
+               }
+               break;
        case 's':
-               ibnd_show_progress(1);
+               cfg->show_progress = 1;
                break;
        case 'l':
                list = LIST_CA_NODE | LIST_SWITCH_NODE | LIST_ROUTER_NODE;
@@ -640,6 +916,9 @@ static int process_opt(void *context, int ch, char *optarg)
        case 'm':
                report_max_hops = 1;
                break;
+       case 'o':
+               cfg->max_smps = strtoul(optarg, NULL, 0);
+               break;
        default:
                return -1;
        }
@@ -649,10 +928,9 @@ static int process_opt(void *context, int ch, char *optarg)
 
 int main(int argc, char **argv)
 {
+       struct ibnd_config config = { 0 };
        ibnd_fabric_t *fabric = NULL;
-
-       struct ibmad_port *ibmad_port;
-       int mgmt_classes[2] = { IB_SMI_CLASS, IB_SMI_DIRECT_CLASS };
+       ibnd_fabric_t *diff_fabric = NULL;
 
        const struct ibdiag_opt opts[] = {
                {"show", 's', 0, NULL, "show more information"},
@@ -662,14 +940,25 @@ int main(int argc, char **argv)
                {"Switch_list", 'S', 0, NULL, "list of connected switches"},
                {"Router_list", 'R', 0, NULL, "list of connected routers"},
                {"node-name-map", 1, 1, "<file>", "node name map file"},
+               {"cache", 2, 1, "<file>",
+                "filename to cache ibnetdiscover data to"},
+               {"load-cache", 3, 1, "<file>",
+                "filename of ibnetdiscover cache to load"},
+               {"diff", 4, 1, "<file>",
+                "filename of ibnetdiscover cache to diff"},
+               {"diffcheck", 5, 1, "<key(s)>",
+                "specify checks to execute for --diff"},
                {"ports", 'p', 0, NULL, "obtain a ports report"},
                {"max_hops", 'm', 0, NULL,
                 "report max hops discovered by the library"},
+               {"outstanding_smps", 'o', 1, NULL,
+                "specify the number of outstanding SMP's which should be "
+                "issued during the scan"},
                {0}
        };
        char usage_args[] = "[topology-file]";
 
-       ibdiag_process_opts(argc, argv, NULL, "sGDL", opts, process_opt,
+       ibdiag_process_opts(argc, argv, &config, "sGDL", opts, process_opt,
                            usage_args, NULL);
 
        f = stdout;
@@ -677,33 +966,43 @@ int main(int argc, char **argv)
        argc -= optind;
        argv += optind;
 
-       if (ibverbose)
-               ibnd_debug(1);
-
-       ibmad_port = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 2);
-       if (!ibmad_port)
-               IBERROR("Failed to open %s port %d", ibd_ca, ibd_ca_port);
-
        if (ibd_timeout)
-               mad_rpc_set_timeout(ibmad_port, ibd_timeout);
+               config.timeout_ms = ibd_timeout;
 
        if (argc && !(f = fopen(argv[0], "w")))
                IBERROR("can't open file %s for writing", argv[0]);
 
        node_name_map = open_node_name_map(node_name_map_file);
 
-       if ((fabric = ibnd_discover_fabric(ibmad_port, NULL, -1)) == NULL)
-               IBERROR("discover failed\n");
+       if (diff_cache_file &&
+           !(diff_fabric = ibnd_load_fabric(diff_cache_file, 0)))
+               IBERROR("loading cached fabric for diff failed\n");
+
+       if (load_cache_file) {
+               if ((fabric = ibnd_load_fabric(load_cache_file, 0)) == NULL)
+                       IBERROR("loading cached fabric failed\n");
+       } else {
+               if ((fabric =
+                    ibnd_discover_fabric(ibd_ca, ibd_ca_port, NULL, &config)) == NULL)
+                       IBERROR("discover failed\n");
+       }
 
        if (ports_report)
                ibnd_iter_nodes(fabric, dump_ports_report, NULL);
        else if (list)
                list_nodes(fabric, list);
+       else if (diff_fabric)
+               diff(diff_fabric, fabric);
        else
                dump_topology(group, fabric);
 
+       if (cache_file)
+               if (ibnd_cache_fabric(fabric, cache_file, 0) < 0)
+                       IBERROR("caching ibnetdiscover data failed\n");
+
        ibnd_destroy_fabric(fabric);
+       if (diff_fabric)
+               ibnd_destroy_fabric(diff_fabric);
        close_node_name_map(node_name_map);
-       mad_rpc_close_port(ibmad_port);
        exit(0);
 }
index 446259d8c7db07b32ee8538f68a879033b30cb3c..dafab1c861c180166c8e8d980b496876996ad939 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2008 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2004-2009 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
index 55e1dd593f475e466b6b905039e38fb0cfe8fed2..499dabcb5105c57ed97a74a7e73d24b4c5e0dff4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2008 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2004-2009 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
 
 #include "ibdiag_common.h"
 
+enum port_ops {
+       QUERY,
+       ENABLE,
+       RESET,
+       DISABLE,
+       SPEED,
+       WIDTH,
+       DOWN,
+       ARM,
+       ACTIVE,
+       VLS,
+       MTU,
+       LID,
+       SMLID,
+       LMC,
+};
+
 struct ibmad_port *srcport;
+int speed = 0; /* no state change */
+int width = 0; /* no state change */
+int lid;
+int smlid;
+int lmc;
+int mtu;
+int vls = 0; /* no state change */
+
+struct {
+       const char *name;
+       int *val;
+       int set;
+} port_args[] = {
+       {"query", NULL, 0},     /* QUERY */
+       {"enable", NULL, 0},    /* ENABLE */
+       {"reset", NULL, 0},     /* RESET */
+       {"disable", NULL, 0},   /* DISABLE */
+       {"speed", &speed, 0},   /* SPEED */
+       {"width", &width, 0},   /* WIDTH */
+       {"down", NULL, 0},      /* DOWN */
+       {"arm", NULL, 0},       /* ARM */
+       {"active", NULL, 0},    /* ACTIVE */
+       {"vls", &vls, 0},       /* VLS */
+       {"mtu", &mtu, 0},       /* MTU */
+       {"lid", &lid, 0},       /* LID */
+       {"smlid", &smlid, 0},   /* SMLID */
+       {"lmc", &lmc, 0},       /* LMC */
+};
+
+#define NPORT_ARGS (sizeof(port_args) / sizeof(port_args[0]))
 
 /*******************************************/
 
+/*
+ * Return 1 if port is a switch, else zero.
+ */
 static int get_node_info(ib_portid_t * dest, uint8_t * data)
 {
        int node_type;
 
        if (!smp_query_via(data, dest, IB_ATTR_NODE_INFO, 0, 0, srcport))
-               return -1;
+               IBERROR("smp query nodeinfo failed");
 
        node_type = mad_get_field(data, 0, IB_NODE_TYPE_F);
        if (node_type == IB_NODE_SWITCH)        /* Switch NodeType ? */
-               return 0;
-       else
                return 1;
+       else
+               return 0;
 }
 
-static int get_port_info(ib_portid_t * dest, uint8_t * data, int portnum,
-                        int port_op)
+static void get_port_info(ib_portid_t * dest, uint8_t * data, int portnum)
+{
+       if (!smp_query_via(data, dest, IB_ATTR_PORT_INFO, portnum, 0, srcport))
+               IBERROR("smp query portinfo failed");
+}
+
+static void show_port_info(ib_portid_t * dest, uint8_t * data, int portnum)
 {
        char buf[2048];
        char val[64];
 
-       if (!smp_query_via(data, dest, IB_ATTR_PORT_INFO, portnum, 0, srcport))
-               return -1;
-
-       if (port_op != 4) {
-               mad_dump_portstates(buf, sizeof buf, data, sizeof data);
-               mad_decode_field(data, IB_PORT_LINK_WIDTH_SUPPORTED_F, val);
-               mad_dump_field(IB_PORT_LINK_WIDTH_SUPPORTED_F,
-                              buf + strlen(buf), sizeof buf - strlen(buf),
-                              val);
-               sprintf(buf + strlen(buf), "%s", "\n");
-               mad_decode_field(data, IB_PORT_LINK_WIDTH_ENABLED_F, val);
-               mad_dump_field(IB_PORT_LINK_WIDTH_ENABLED_F, buf + strlen(buf),
-                              sizeof buf - strlen(buf), val);
-               sprintf(buf + strlen(buf), "%s", "\n");
-               mad_decode_field(data, IB_PORT_LINK_WIDTH_ACTIVE_F, val);
-               mad_dump_field(IB_PORT_LINK_WIDTH_ACTIVE_F, buf + strlen(buf),
-                              sizeof buf - strlen(buf), val);
-               sprintf(buf + strlen(buf), "%s", "\n");
-               mad_decode_field(data, IB_PORT_LINK_SPEED_SUPPORTED_F, val);
-               mad_dump_field(IB_PORT_LINK_SPEED_SUPPORTED_F,
-                              buf + strlen(buf), sizeof buf - strlen(buf),
-                              val);
-               sprintf(buf + strlen(buf), "%s", "\n");
-               mad_decode_field(data, IB_PORT_LINK_SPEED_ENABLED_F, val);
-               mad_dump_field(IB_PORT_LINK_SPEED_ENABLED_F, buf + strlen(buf),
-                              sizeof buf - strlen(buf), val);
-               sprintf(buf + strlen(buf), "%s", "\n");
-               mad_decode_field(data, IB_PORT_LINK_SPEED_ACTIVE_F, val);
-               mad_dump_field(IB_PORT_LINK_SPEED_ACTIVE_F, buf + strlen(buf),
-                              sizeof buf - strlen(buf), val);
-               sprintf(buf + strlen(buf), "%s", "\n");
-       } else {
-               mad_decode_field(data, IB_PORT_LINK_SPEED_ENABLED_F, val);
-               mad_dump_field(IB_PORT_LINK_SPEED_ENABLED_F, buf, sizeof buf,
-                              val);
-               sprintf(buf + strlen(buf), "%s", "\n");
-       }
+       mad_dump_portstates(buf, sizeof buf, data, sizeof data);
+       mad_decode_field(data, IB_PORT_LID_F, val);
+       mad_dump_field(IB_PORT_LID_F, buf + strlen(buf),
+                      sizeof buf - strlen(buf), val);
+       sprintf(buf + strlen(buf), "%s", "\n");
+       mad_decode_field(data, IB_PORT_SMLID_F, val);
+       mad_dump_field(IB_PORT_SMLID_F, buf + strlen(buf),
+                      sizeof buf - strlen(buf), val);
+       sprintf(buf + strlen(buf), "%s", "\n");
+       mad_decode_field(data, IB_PORT_LMC_F, val);
+       mad_dump_field(IB_PORT_LMC_F, buf + strlen(buf),
+                      sizeof buf - strlen(buf), val);
+       sprintf(buf + strlen(buf), "%s", "\n");
+       mad_decode_field(data, IB_PORT_LINK_WIDTH_SUPPORTED_F, val);
+       mad_dump_field(IB_PORT_LINK_WIDTH_SUPPORTED_F, buf + strlen(buf),
+                      sizeof buf - strlen(buf), val);
+       sprintf(buf + strlen(buf), "%s", "\n");
+       mad_decode_field(data, IB_PORT_LINK_WIDTH_ENABLED_F, val);
+       mad_dump_field(IB_PORT_LINK_WIDTH_ENABLED_F, buf + strlen(buf),
+                      sizeof buf - strlen(buf), val);
+       sprintf(buf + strlen(buf), "%s", "\n");
+       mad_decode_field(data, IB_PORT_LINK_WIDTH_ACTIVE_F, val);
+       mad_dump_field(IB_PORT_LINK_WIDTH_ACTIVE_F, buf + strlen(buf),
+                      sizeof buf - strlen(buf), val);
+       sprintf(buf + strlen(buf), "%s", "\n");
+       mad_decode_field(data, IB_PORT_LINK_SPEED_SUPPORTED_F, val);
+       mad_dump_field(IB_PORT_LINK_SPEED_SUPPORTED_F, buf + strlen(buf),
+                      sizeof buf - strlen(buf), val);
+       sprintf(buf + strlen(buf), "%s", "\n");
+       mad_decode_field(data, IB_PORT_LINK_SPEED_ENABLED_F, val);
+       mad_dump_field(IB_PORT_LINK_SPEED_ENABLED_F, buf + strlen(buf),
+                      sizeof buf - strlen(buf), val);
+       sprintf(buf + strlen(buf), "%s", "\n");
+       mad_decode_field(data, IB_PORT_LINK_SPEED_ACTIVE_F, val);
+       mad_dump_field(IB_PORT_LINK_SPEED_ACTIVE_F, buf + strlen(buf),
+                      sizeof buf - strlen(buf), val);
+       sprintf(buf + strlen(buf), "%s", "\n");
 
        printf("# Port info: %s port %d\n%s", portid2str(dest), portnum, buf);
-       return 0;
 }
 
-static int set_port_info(ib_portid_t * dest, uint8_t * data, int portnum,
-                        int port_op)
+static void set_port_info(ib_portid_t * dest, uint8_t * data, int portnum)
 {
-       char buf[2048];
-       char val[64];
-
        if (!smp_set_via(data, dest, IB_ATTR_PORT_INFO, portnum, 0, srcport))
-               return -1;
-
-       if (port_op != 4)
-               mad_dump_portstates(buf, sizeof buf, data, sizeof data);
-       else {
-               mad_decode_field(data, IB_PORT_LINK_SPEED_ENABLED_F, val);
-               mad_dump_field(IB_PORT_LINK_SPEED_ENABLED_F, buf, sizeof buf,
-                              val);
-               sprintf(buf + strlen(buf), "%s", "\n");
-       }
+               IBERROR("smp set portinfo failed");
 
        printf("\nAfter PortInfo set:\n");
-       printf("# Port info: %s port %d\n%s", portid2str(dest), portnum, buf);
-       return 0;
+       show_port_info(dest, data, portnum);
 }
 
 static int get_link_width(int lwe, int lws)
@@ -201,22 +241,23 @@ int main(int argc, char **argv)
        int mgmt_classes[3] =
            { IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS };
        ib_portid_t portid = { 0 };
-       int err;
-       int port_op = 0;        /* default to query */
-       int speed = 15;
-       int is_switch = 1;
+       int port_op = -1;
+       int is_switch;
        int state, physstate, lwe, lws, lwa, lse, lss, lsa;
        int peerlocalportnum, peerlwe, peerlws, peerlwa, peerlse, peerlss,
            peerlsa;
-       int width = 255, peerwidth, peerspeed;
+       int peerwidth, peerspeed;
        uint8_t data[IB_SMP_DATA_SIZE];
        ib_portid_t peerportid = { 0 };
        int portnum = 0;
        ib_portid_t selfportid = { 0 };
        int selfport = 0;
-
+       int changed = 0;
+       int i;
+       long val;
        char usage_args[] = "<dest dr_path|lid|guid> <portnum> [<op>]\n"
-           "\nSupported ops: enable, disable, reset, speed, width, query";
+           "\nSupported ops: enable, disable, reset, speed, width, query,\n"
+           "\tdown, arm, active, vls, mtu, lid, smlid, lmc\n";
        const char *usage_examples[] = {
                "3 1 disable\t\t\t# by lid",
                "-G 0x2C9000100D051 1 enable\t# by guid",
@@ -224,6 +265,7 @@ int main(int argc, char **argv)
                "3 1 reset\t\t\t# by lid",
                "3 1 speed 1\t\t\t# by lid",
                "3 1 width 1\t\t\t# by lid",
+               "-D 0 1 lid 0x1234 arm\t\t# by direct route",
                NULL
        };
 
@@ -247,78 +289,129 @@ int main(int argc, char **argv)
        if (argc > 1)
                portnum = strtol(argv[1], 0, 0);
 
-       /* First, make sure it is a switch port if it is a "set" */
-       if (argc >= 3) {
-               if (!strcmp(argv[2], "enable"))
-                       port_op = 1;
-               else if (!strcmp(argv[2], "disable"))
-                       port_op = 2;
-               else if (!strcmp(argv[2], "reset"))
-                       port_op = 3;
-               else if (!strcmp(argv[2], "speed")) {
-                       if (argc < 4)
-                               IBERROR
-                                   ("speed requires an additional parameter");
-                       port_op = 4;
-                       /* Parse speed value */
-                       speed = strtoul(argv[3], 0, 0);
-                       if (speed > 15)
-                               IBERROR("invalid speed value %d", speed);
-               } else if (!strcmp(argv[2], "width")) {
-                       if (argc < 4)
-                               IBERROR
-                                   ("width requires an additional parameter");
-                       port_op = 5;
-                       /* Parse width value */
-                       width = strtoul(argv[3], 0, 0);
-                       if (width > 15 && width != 255)
-                               IBERROR("invalid width value %d", width);
+       for (i = 2; i < argc; i++) {
+               int j;
+
+               for (j = 0; j < NPORT_ARGS; j++) {
+                       if (strcmp(argv[i], port_args[j].name))
+                               continue;
+                       port_args[j].set = 1;
+                       if (!port_args[j].val) {
+                               if (port_op >= 0)
+                                       IBERROR("%s only one of: ",
+                                               "query, enable, disable, "
+                                               "reset, down, arm, active, "
+                                               "can be specified",
+                                               port_args[j].name);
+                               port_op = j;
+                               break;
+                       }
+                       if (++i >= argc)
+                               IBERROR("%s requires an additional parameter",
+                                       port_args[j].name);
+                       val = strtol(argv[i], 0, 0);
+                       switch (j) {
+                       case SPEED:
+                               if (val < 0 || val > 15)
+                                       IBERROR("invalid speed value %ld", val);
+                               break;
+                       case WIDTH:
+                               if (val < 0 || (val > 15 && val != 255))
+                                       IBERROR("invalid width value %ld", val);
+                               break;
+                       case VLS:
+                               if (val <= 0 || val > 5)
+                                       IBERROR("invalid vls value %ld", val);
+                               break;
+                       case MTU:
+                               if (val <= 0 || val > 5)
+                                       IBERROR("invalid mtu value %ld", val);
+                               break;
+                       case LID:
+                               if (val <= 0 || val >= 0xC000)
+                                       IBERROR("invalid lid value 0x%lx", val);
+                               break;
+                       case SMLID:
+                               if (val <= 0 || val >= 0xC000)
+                                       IBERROR("invalid smlid value 0x%lx",
+                                               val);
+                               break;
+                       case LMC:
+                               if (val < 0 || val > 7)
+                                       IBERROR("invalid lmc value %ld", val);
+                       }
+                       *port_args[j].val = (int)val;
+                       changed = 1;
+                       break;
                }
+               if (j == NPORT_ARGS)
+                       IBERROR("invalid operation: %s", argv[i]);
        }
+       if (port_op < 0)
+               port_op = QUERY;
 
-       err = get_node_info(&portid, data);
-       if (err < 0)
-               IBERROR("smp query nodeinfo failed");
-       if (err) {              /* not switch */
-               if (port_op == 0)       /* query op */
-                       is_switch = 0;
-               else if (port_op == 2)  /* disable */
-                       IBERROR("Node type not switch - disable not allowed");
-       }
+       is_switch = get_node_info(&portid, data);
 
-       if (port_op)
-               printf("Initial PortInfo:\n");
+       if (port_op != QUERY || changed)
+               printf("Initial %s PortInfo:\n", is_switch ? "Switch" : "CA");
        else
-               printf("PortInfo:\n");
-       err = get_port_info(&portid, data, portnum, port_op);
-       if (err < 0)
-               IBERROR("smp query portinfo failed");
-
-       /* Only if one of the "set" options is chosen */
-       if (port_op) {
-               if ((port_op == 1) || (port_op == 3)) { /* Enable or Reset port */
-                       mad_set_field(data, 0, IB_PORT_PHYS_STATE_F, 2);        /* Polling */
-                       mad_set_field(data, 0, IB_PORT_STATE_F, 0);     /* No Change */
-               } else if (port_op == 2) {      /* Disable port */
+               printf("%s PortInfo:\n", is_switch ? "Switch" : "CA");
+       get_port_info(&portid, data, portnum);
+       show_port_info(&portid, data, portnum);
+
+       if (port_op != QUERY || changed) {
+               /*
+                * If we aren't setting the LID and the LID is the default,
+                * the SMA command will fail due to an invalid LID.
+                * Set it to something unlikely but valid.
+                */
+               val = mad_get_field(data, 0, IB_PORT_LID_F);
+               if (!port_args[LID].set && (!val || val == 0xFFFF))
+                       mad_set_field(data, 0, IB_PORT_LID_F, 0x1234);
+               val = mad_get_field(data, 0, IB_PORT_SMLID_F);
+               if (!port_args[SMLID].set && (!val || val == 0xFFFF))
+                       mad_set_field(data, 0, IB_PORT_SMLID_F, 0x1234);
+               mad_set_field(data, 0, IB_PORT_STATE_F, 0);     /* NOP */
+               mad_set_field(data, 0, IB_PORT_PHYS_STATE_F, 0);        /* NOP */
+
+               switch (port_op) {
+               case ENABLE:
+               case RESET:
+                       /* Polling */
+                       mad_set_field(data, 0, IB_PORT_PHYS_STATE_F, 2);
+                       break;
+               case DISABLE:
                        printf("Disable may be irreversible\n");
-                       mad_set_field(data, 0, IB_PORT_STATE_F, 1);     /* Down */
-                       mad_set_field(data, 0, IB_PORT_PHYS_STATE_F, 3);        /* Disabled */
-               } else if (port_op == 4) {      /* Set speed */
-                       mad_set_field(data, 0, IB_PORT_LINK_SPEED_ENABLED_F,
-                                     speed);
-                       mad_set_field(data, 0, IB_PORT_STATE_F, 0);
-                       mad_set_field(data, 0, IB_PORT_PHYS_STATE_F, 0);
-               } else if (port_op == 5) {      /* Set width */
-                       mad_set_field(data, 0, IB_PORT_LINK_WIDTH_ENABLED_F,
-                                     width);
-                       mad_set_field(data, 0, IB_PORT_STATE_F, 0);
-                       mad_set_field(data, 0, IB_PORT_PHYS_STATE_F, 0);
+                       mad_set_field(data, 0, IB_PORT_PHYS_STATE_F, 3);
+                       break;
+               case DOWN:
+                       mad_set_field(data, 0, IB_PORT_STATE_F, 1);
+                       break;
+               case ARM:
+                       mad_set_field(data, 0, IB_PORT_STATE_F, 3);
+                       break;
+               case ACTIVE:
+                       mad_set_field(data, 0, IB_PORT_STATE_F, 4);
+                       break;
                }
 
-               err = set_port_info(&portid, data, portnum, port_op);
-               if (err < 0)
-                       IBERROR("smp set portinfo failed");
-               /* query op - only compare peer port if switch port, exclude SP0 */
+               /* always set enabled speed/width - defaults to NOP */
+               mad_set_field(data, 0, IB_PORT_LINK_SPEED_ENABLED_F, speed);
+               mad_set_field(data, 0, IB_PORT_LINK_WIDTH_ENABLED_F, width);
+
+               if (port_args[VLS].set)
+                       mad_set_field(data, 0, IB_PORT_OPER_VLS_F, vls);
+               if (port_args[MTU].set)
+                       mad_set_field(data, 0, IB_PORT_NEIGHBOR_MTU_F, mtu);
+               if (port_args[LID].set)
+                       mad_set_field(data, 0, IB_PORT_LID_F, lid);
+               if (port_args[SMLID].set)
+                       mad_set_field(data, 0, IB_PORT_SMLID_F, smlid);
+               if (port_args[LMC].set)
+                       mad_set_field(data, 0, IB_PORT_LMC_F, lmc);
+
+               set_port_info(&portid, data, portnum);
+
        } else if (is_switch && portnum) {
                /* Now, make sure PortState is Active */
                /* Or is PortPhysicalState LinkUp sufficient ? */
@@ -351,20 +444,15 @@ int main(int argc, char **argv)
                        peerportid.drpath.drdlid = 0xffff;
 
                        /* Get peer port NodeInfo to obtain peer port number */
-                       err = get_node_info(&peerportid, data);
-                       if (err < 0)
-                               IBERROR("smp query nodeinfo failed");
+                       get_node_info(&peerportid, data);
 
                        mad_decode_field(data, IB_NODE_LOCAL_PORT_F,
                                         &peerlocalportnum);
 
                        printf("Peer PortInfo:\n");
                        /* Get peer port characteristics */
-                       err =
-                           get_port_info(&peerportid, data, peerlocalportnum,
-                                         port_op);
-                       if (err < 0)
-                               IBERROR("smp query peer portinfo failed");
+                       get_port_info(&peerportid, data, peerlocalportnum);
+                       show_port_info(&peerportid, data, peerlocalportnum);
 
                        mad_decode_field(data, IB_PORT_LINK_WIDTH_ENABLED_F,
                                         &peerlwe);
index e67d338efc5a77e8a1949a15d538933374a1fccb..f04e47f03f561cc863446a9dc3e7a4df6d509348 100644 (file)
@@ -1,7 +1,8 @@
 /*
- * Copyright (c) 2004-2007 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
  * Copyright (c) 2007 Xsigo Systems Inc.  All rights reserved.
  * Copyright (c) 2008 Lawrence Livermore National Lab.  All rights reserved.
+ * Copyright (c) 2009 HNR Consulting.  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
 struct ibmad_port *ibmad_port;
 static char *node_name_map_file = NULL;
 static nn_map_t *node_name_map = NULL;
+static char *load_cache_file = NULL;
+
 int data_counters = 0;
 int port_config = 0;
 uint64_t node_guid = 0;
 char *node_guid_str = NULL;
+#define SUP_MAX 64
 int sup_total = 0;
-enum MAD_FIELDS *suppressed_fields = NULL;
+enum MAD_FIELDS suppressed_fields[SUP_MAX];
 char *dr_path = NULL;
 uint8_t node_type_to_print = 0;
+unsigned clear_errors = 0, clear_counts = 0, details = 0;
 
 #define PRINT_SWITCH 0x1
 #define PRINT_CA     0x2
 #define PRINT_ROUTER 0x4
-#define PRINT_ALL 0xFF /* all nodes default flag */
+#define PRINT_ALL 0xFF         /* all nodes default flag */
 
 static unsigned int get_max(unsigned int num)
 {
-       unsigned int v = num;   // 32-bit word to find the log base 2 of
-       unsigned r = 0;         // r will be lg(v)
+       unsigned r = 0;         // r will be lg(num)
 
-       while (v >>= 1)         // unroll for more speed...
-       {
+       while (num >>= 1)       // unroll for more speed...
                r++;
-       }
 
        return (1 << r);
 }
@@ -95,29 +97,27 @@ static void get_msg(char *width_msg, char *speed_msg, int msg_size,
                                     & mad_get_field(port->remoteport->info, 0,
                                                     IB_PORT_LINK_WIDTH_SUPPORTED_F));
        if ((max_width & mad_get_field(port->info, 0,
-                                      IB_PORT_LINK_WIDTH_ACTIVE_F)) == 0) {
+                                      IB_PORT_LINK_WIDTH_ACTIVE_F)) == 0)
                // we are not at the max supported width
                // print what we could be at.
                snprintf(width_msg, msg_size, "Could be %s",
                         mad_dump_val(IB_PORT_LINK_WIDTH_ACTIVE_F,
                                      buf, 64, &max_width));
-       }
 
        max_speed = get_max(mad_get_field(port->info, 0,
                                          IB_PORT_LINK_SPEED_SUPPORTED_F)
                            & mad_get_field(port->remoteport->info, 0,
                                            IB_PORT_LINK_SPEED_SUPPORTED_F));
        if ((max_speed & mad_get_field(port->info, 0,
-                                      IB_PORT_LINK_SPEED_ACTIVE_F)) == 0) {
+                                      IB_PORT_LINK_SPEED_ACTIVE_F)) == 0)
                // we are not at the max supported speed
                // print what we could be at.
                snprintf(speed_msg, msg_size, "Could be %s",
                         mad_dump_val(IB_PORT_LINK_SPEED_ACTIVE_F,
                                      buf, 64, &max_speed));
-       }
 }
 
-static void print_port_config(ibnd_node_t * node, int portnum)
+static void print_port_config(char *node_name, ibnd_node_t * node, int portnum)
 {
        char width[64], speed[64], state[64], physstate[64];
        char remote_str[256];
@@ -142,16 +142,23 @@ static void print_port_config(ibnd_node_t * node, int portnum)
        width_msg[0] = '\0';
        speed_msg[0] = '\0';
 
-       snprintf(link_str, 256, "(%3s %s %6s/%8s)",
-                mad_dump_val(IB_PORT_LINK_WIDTH_ACTIVE_F, width, 64, &iwidth),
-                mad_dump_val(IB_PORT_LINK_SPEED_ACTIVE_F, speed, 64, &ispeed),
-                mad_dump_val(IB_PORT_STATE_F, state, 64, &istate),
-                mad_dump_val(IB_PORT_PHYS_STATE_F, physstate, 64, &iphystate));
+       /* C14-24.2.1 states that a down port allows for invalid data to be
+        * returned for all PortInfo components except PortState and
+        * PortPhysicalState */
+       if (istate != IB_LINK_DOWN) {
+               snprintf(link_str, 256, "(%3s %9s %6s/%8s)",
+                        mad_dump_val(IB_PORT_LINK_WIDTH_ACTIVE_F, width, 64, &iwidth),
+                        mad_dump_val(IB_PORT_LINK_SPEED_ACTIVE_F, speed, 64, &ispeed),
+                        mad_dump_val(IB_PORT_STATE_F, state, 64, &istate),
+                        mad_dump_val(IB_PORT_PHYS_STATE_F, physstate, 64, &iphystate));
+       } else {
+               snprintf(link_str, 256, "(              %6s/%8s)",
+                        mad_dump_val(IB_PORT_STATE_F, state, 64, &istate),
+                        mad_dump_val(IB_PORT_PHYS_STATE_F, physstate, 64, &iphystate));
+       }
 
        if (port->remoteport) {
-               char *remap =
-                   remap_node_name(node_name_map, port->remoteport->node->guid,
-                                   port->remoteport->node->nodedesc);
+               char *rem_node_name = NULL;
 
                if (port->remoteport->ext_portnum)
                        snprintf(ext_port_str, 256, "%d",
@@ -161,14 +168,20 @@ static void print_port_config(ibnd_node_t * node, int portnum)
 
                get_msg(width_msg, speed_msg, 256, port);
 
+               rem_node_name = remap_node_name(node_name_map,
+                                               port->remoteport->node->guid,
+                                               port->remoteport->node->
+                                               nodedesc);
+
                snprintf(remote_str, 256,
                         "0x%016" PRIx64 " %6d %4d[%2s] \"%s\" (%s %s)\n",
                         port->remoteport->node->guid,
                         port->remoteport->base_lid ? port->remoteport->
                         base_lid : port->remoteport->node->smalid,
-                        port->remoteport->portnum, ext_port_str, remap,
+                        port->remoteport->portnum, ext_port_str, rem_node_name,
                         width_msg, speed_msg);
-               free(remap);
+
+               free(rem_node_name);
        } else
                snprintf(remote_str, 256, "           [  ] \"\" ( )\n");
 
@@ -189,50 +202,95 @@ static void print_port_config(ibnd_node_t * node, int portnum)
 static int suppress(enum MAD_FIELDS field)
 {
        int i = 0;
-       if (suppressed_fields)
-               for (i = 0; i < sup_total; i++) {
-                       if (field == suppressed_fields[i])
-                               return (1);
-               }
-       return (0);
+       for (i = 0; i < sup_total; i++)
+               if (field == suppressed_fields[i])
+                       return 1;
+       return 0;
 }
 
 static void report_suppressed(void)
 {
        int i = 0;
-       if (suppressed_fields) {
-               printf("Suppressing:");
-               for (i = 0; i < sup_total; i++) {
-                       printf(" %s", mad_field_name(suppressed_fields[i]));
-               }
-               printf("\n");
+       printf("Suppressing:");
+       for (i = 0; i < sup_total; i++)
+               printf(" %s", mad_field_name(suppressed_fields[i]));
+       printf("\n");
+}
+
+static int query_and_dump(char *buf, size_t size, ib_portid_t * portid,
+                         ibnd_node_t * node, char *node_name, int portnum,
+                         const char *attr_name, uint16_t attr_id,
+                         int start_field, int end_field)
+{
+       uint8_t pc[1024];
+       uint32_t val = 0;
+       int i, n;
+
+       memset(pc, 0, sizeof(pc));
+
+       if (!pma_query_via(pc, portid, portnum, ibd_timeout, attr_id,
+                          ibmad_port)) {
+               IBWARN("%s query failed on %s, %s port %d", attr_name,
+                      node_name, portid2str(portid), portnum);
+               return 0;
        }
+
+       for (n = 0, i = start_field; i < end_field; i++) {
+               mad_decode_field(pc, i, (void *)&val);
+               if (val)
+                       n += snprintf(buf + n, size - n, " [%s == %u]",
+                                     mad_field_name(i), val);
+       }
+
+       return n;
 }
 
-static void print_results(ibnd_node_t * node, uint8_t * pc, int portnum,
+static void print_results(ib_portid_t * portid, char *node_name,
+                         ibnd_node_t * node, uint8_t * pc, int portnum,
                          int *header_printed)
 {
        char buf[1024];
        char *str = buf;
        uint32_t val = 0;
-       int n = 0;
-       int i = 0;
+       int i, n;
 
        for (n = 0, i = IB_PC_ERR_SYM_F; i <= IB_PC_VL15_DROPPED_F; i++) {
                if (suppress(i))
                        continue;
 
+               /* this is not a counter, skip it */
+               if (i == IB_PC_COUNTER_SELECT2_F)
+                       continue;
+
                mad_decode_field(pc, i, (void *)&val);
                if (val)
-                       n += snprintf(str + n, 1024 - n, " [%s == %d]",
+                       n += snprintf(str + n, 1024 - n, " [%s == %u]",
                                      mad_field_name(i), val);
+
+               /* If there are PortXmitDiscards, get details (if supported) */
+               if (i == IB_PC_XMT_DISCARDS_F && details && val) {
+                       n += query_and_dump(str + n, sizeof(buf) - n, portid,
+                                           node, node_name, portnum,
+                                           "PortXmitDiscardDetails",
+                                           IB_GSI_PORT_XMIT_DISCARD_DETAILS,
+                                           IB_PC_RCV_LOCAL_PHY_ERR_F,
+                                           IB_PC_RCV_ERR_LAST_F);
+                       /* If there are PortRcvErrors, get details (if supported) */
+               } else if (i == IB_PC_ERR_RCV_F && details && val) {
+                       n += query_and_dump(str + n, sizeof(buf) - n, portid,
+                                           node, node_name, portnum,
+                                           "PortRcvErrorDetails",
+                                           IB_GSI_PORT_RCV_ERROR_DETAILS,
+                                           IB_PC_XMT_INACT_DISC_F,
+                                           IB_PC_XMT_DISC_LAST_F);
+               }
        }
 
        if (!suppress(IB_PC_XMT_WAIT_F)) {
                mad_decode_field(pc, IB_PC_XMT_WAIT_F, (void *)&val);
                if (val)
-                       n += snprintf(str + n, 1024 - n, " [%s == %d]",
-                                     mad_field_name(i), val);
+                       n += snprintf(str + n, 1024 - n, " [%s == %u]",
+                                     mad_field_name(IB_PC_XMT_WAIT_F), val);
        }
 
        /* if we found errors. */
@@ -243,65 +301,97 @@ static void print_results(ibnd_node_t * node, uint8_t * pc, int portnum,
                                mad_decode_field(pc, i, (void *)&val64);
                                if (val64)
                                        n += snprintf(str + n, 1024 - n,
-                                                     " [%s == %" PRId64 "]",
+                                                     " [%s == %" PRIu64 "]",
                                                      mad_field_name(i), val64);
                        }
 
                if (!*header_printed) {
-                       char *nodename =
-                           remap_node_name(node_name_map, node->guid,
-                                           node->nodedesc);
                        printf("Errors for 0x%" PRIx64 " \"%s\"\n", node->guid,
-                              nodename);
+                              node_name);
                        *header_printed = 1;
-                       free(nodename);
                }
 
                printf("   GUID 0x%" PRIx64 " port %d:%s\n", node->guid,
                       portnum, str);
                if (port_config)
-                       print_port_config(node, portnum);
+                       print_port_config(node_name, node, portnum);
        }
 }
 
-static void print_port(ibnd_node_t * node, int portnum, int *header_printed)
+static int query_cap_mask(ib_portid_t * portid, char *node_name, int portnum,
+                         uint16_t * cap_mask)
 {
        uint8_t pc[1024];
-       uint16_t cap_mask;
-       ib_portid_t portid = { 0 };
-       char *nodename =
-           remap_node_name(node_name_map, node->guid, node->nodedesc);
-
-       if (node->type == IB_NODE_SWITCH)
-               ib_portid_set(&portid, node->smalid, 0, 0);
-       else
-               ib_portid_set(&portid, node->ports[portnum]->base_lid, 0, 0);
+       uint16_t rc_cap_mask;
 
        /* PerfMgt ClassPortInfo is a required attribute */
-       if (!pma_query_via(pc, &portid, portnum, ibd_timeout, CLASS_PORT_INFO,
+       if (!pma_query_via(pc, portid, portnum, ibd_timeout, CLASS_PORT_INFO,
                           ibmad_port)) {
                IBWARN("classportinfo query failed on %s, %s port %d",
-                      nodename, portid2str(&portid), portnum);
-               goto cleanup;
+                      node_name, portid2str(portid), portnum);
+               return -1;
        }
+
        /* ClassPortInfo should be supported as part of libibmad */
-       memcpy(&cap_mask, pc + 2, sizeof(cap_mask));    /* CapabilityMask */
+       memcpy(&rc_cap_mask, pc + 2, sizeof(rc_cap_mask));      /* CapabilityMask */
 
-       if (!pma_query_via(pc, &portid, portnum, ibd_timeout,
+       *cap_mask = ntohs(rc_cap_mask);
+       return 0;
+}
+
+static void print_port(ib_portid_t * portid, uint16_t cap_mask, char *node_name,
+                      ibnd_node_t * node, int portnum, int *header_printed)
+{
+       uint8_t pc[1024];
+
+       memset(pc, 0, 1024);
+
+       if (!pma_query_via(pc, portid, portnum, ibd_timeout,
                           IB_GSI_PORT_COUNTERS, ibmad_port)) {
-               IBWARN("IB_GSI_PORT_COUNTERS query failed on %s, %s port %d\n",
-                      nodename, portid2str(&portid), portnum);
-               goto cleanup;
+               IBWARN("IB_GSI_PORT_COUNTERS query failed on %s, %s port %d",
+                      node_name, portid2str(portid), portnum);
+               return;
        }
        if (!(cap_mask & 0x1000)) {
-               /* if PortCounters:PortXmitWait not suppported clear this counter */
+               /* if PortCounters:PortXmitWait not supported clear this counter */
                uint32_t foo = 0;
                mad_encode_field(pc, IB_PC_XMT_WAIT_F, &foo);
        }
-       print_results(node, pc, portnum, header_printed);
+       print_results(portid, node_name, node, pc, portnum, header_printed);
+}
+
+static void clear_port(ib_portid_t * portid, uint16_t cap_mask,
+                      char *node_name, int port)
+{
+       uint8_t pc[1024];
+       /* bits defined in Table 228 PortCounters CounterSelect and
+        * CounterSelect2
+        */
+       uint32_t mask = 0;
 
-cleanup:
-       free(nodename);
+       if (!clear_errors && !clear_counts)
+               return;
+
+       if (clear_errors) {
+               mask |= 0xFFF;
+               if (cap_mask & 0x1000)
+                       mask |= 0x10000;
+       }
+       if (clear_counts)
+               mask |= 0xF000;
+
+       if (!performance_reset_via(pc, portid, port, mask, ibd_timeout,
+                                  IB_GSI_PORT_COUNTERS, ibmad_port))
+               IBERROR("Failed to reset errors %s port %d", node_name, port);
+
+       if (details && clear_errors) {
+               performance_reset_via(pc, portid, port, 0xf, ibd_timeout,
+                                     IB_GSI_PORT_XMIT_DISCARD_DETAILS,
+                                     ibmad_port);
+               performance_reset_via(pc, portid, port, 0x3f, ibd_timeout,
+                                     IB_GSI_PORT_RCV_ERROR_DETAILS,
+                                     ibmad_port);
+       }
 }
 
 void print_node(ibnd_node_t * node, void *user_data)
@@ -310,6 +400,10 @@ void print_node(ibnd_node_t * node, void *user_data)
        int p = 0;
        int startport = 1;
        int type = 0;
+       int all_port_sup = 0;
+       ib_portid_t portid = { 0 };
+       uint16_t cap_mask = 0;
+       char *node_name = NULL;
 
        switch (node->type) {
        case IB_NODE_SWITCH:
@@ -329,18 +423,44 @@ void print_node(ibnd_node_t * node, void *user_data)
        if (node->type == IB_NODE_SWITCH && node->smaenhsp0)
                startport = 0;
 
+       node_name = remap_node_name(node_name_map, node->guid, node->nodedesc);
+
        for (p = startport; p <= node->numports; p++) {
                if (node->ports[p]) {
-                       print_port(node, p, &header_printed);
+                       if (node->type == IB_NODE_SWITCH)
+                               ib_portid_set(&portid, node->smalid, 0, 0);
+                       else
+                               ib_portid_set(&portid, node->ports[p]->base_lid,
+                                             0, 0);
+
+                       if (query_cap_mask(&portid, node_name, p, &cap_mask) <
+                           0)
+                               continue;
+
+                       if (cap_mask & 0x100)
+                               all_port_sup = 1;
+
+                       print_port(&portid, cap_mask, node_name, node, p,
+                                  &header_printed);
+                       if (!all_port_sup)
+                               clear_port(&portid, cap_mask, node_name, p);
                }
        }
+
+       if (all_port_sup)
+               clear_port(&portid, cap_mask, node_name, 0xFF);
+
+       free(node_name);
 }
 
 static void add_suppressed(enum MAD_FIELDS field)
 {
-       suppressed_fields = realloc(suppressed_fields, sizeof(enum MAD_FIELDS));
-       suppressed_fields[sup_total] = field;
-       sup_total++;
+       if (sup_total >= SUP_MAX) {
+               IBWARN("Maximum (%d) fields have been suppressed; skipping %s",
+                      sup_total, mad_field_name(field));
+               return;
+       }
+       suppressed_fields[sup_total++] = field;
 }
 
 static void calculate_suppressed_fields(char *str)
@@ -351,11 +471,9 @@ static void calculate_suppressed_fields(char *str)
 
        val = strtok_r(tmp, ",", &lasts);
        while (val) {
-               for (f = IB_PC_FIRST_F; f <= IB_PC_LAST_F; f++) {
-                       if (strcmp(val, mad_field_name(f)) == 0) {
+               for (f = IB_PC_FIRST_F; f <= IB_PC_LAST_F; f++)
+                       if (strcmp(val, mad_field_name(f)) == 0)
                                add_suppressed(f);
-                       }
-               }
                val = strtok_r(NULL, ",", &lasts);
        }
 
@@ -364,6 +482,7 @@ static void calculate_suppressed_fields(char *str)
 
 static int process_opt(void *context, int ch, char *optarg)
 {
+       struct ibnd_config *cfg = context;
        switch (ch) {
        case 's':
                calculate_suppressed_fields(optarg);
@@ -387,6 +506,12 @@ static int process_opt(void *context, int ch, char *optarg)
        case 5:
                node_type_to_print |= PRINT_ROUTER;
                break;
+       case 6:
+               details = 1;
+               break;
+       case 7:
+               load_cache_file = strdup(optarg);
+               break;
        case 'G':
        case 'S':
                node_guid_str = optarg;
@@ -400,6 +525,15 @@ static int process_opt(void *context, int ch, char *optarg)
                break;
        case 'R':               /* nop */
                break;
+       case 'k':
+               clear_errors = 1;
+               break;
+       case 'K':
+               clear_counts = 1;
+               break;
+       case 'o':
+               cfg->max_smps = strtoul(optarg, NULL, 0);
+               break;
        default:
                return -1;
        }
@@ -409,6 +543,7 @@ static int process_opt(void *context, int ch, char *optarg)
 
 int main(int argc, char **argv)
 {
+       struct ibnd_config config = { 0 };
        int resolved = -1;
        ib_portid_t portid = { 0 };
        int rc = 0;
@@ -437,11 +572,22 @@ int main(int argc, char **argv)
                {"switch", 3, 0, NULL, "print data for switches only"},
                {"ca", 4, 0, NULL, "print data for CA's only"},
                {"router", 5, 0, NULL, "print data for routers only"},
+               {"details", 6, 0, NULL, "include transmit discard details"},
+               {"clear-errors", 'k', 0, NULL,
+                "Clear error counters after read"},
+               {"clear-counts", 'K', 0, NULL,
+                "Clear data counters after read"},
+               {"load-cache", 7, 1, "<file>",
+                "filename of ibnetdiscover cache to load"},
+               {"outstanding_smps", 'o', 1, NULL,
+                "specify the number of outstanding SMP's which should be "
+                "issued during the scan"},
                {0}
        };
        char usage_args[] = "";
 
-       ibdiag_process_opts(argc, argv, NULL, "scnSrRDGL", opts, process_opt,
+       memset(suppressed_fields, 0, sizeof suppressed_fields);
+       ibdiag_process_opts(argc, argv, &config, "scnSrRDGL", opts, process_opt,
                            usage_args, NULL);
 
        argc -= optind;
@@ -450,47 +596,59 @@ int main(int argc, char **argv)
        if (!node_type_to_print)
                node_type_to_print = PRINT_ALL;
 
-       if (ibverbose)
-               ibnd_debug(1);
-
        ibmad_port = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 4);
        if (!ibmad_port)
                IBERROR("Failed to open port; %s:%d\n", ibd_ca, ibd_ca_port);
 
-       if (ibd_timeout)
+       if (ibd_timeout) {
                mad_rpc_set_timeout(ibmad_port, ibd_timeout);
+               config.timeout_ms = ibd_timeout;
+       }
 
        node_name_map = open_node_name_map(node_name_map_file);
 
+       if (dr_path && load_cache_file) {
+               fprintf(stderr, "Cannot specify cache and direct route path\n");
+               exit(1);
+       }
+
        /* limit the scan the fabric around the target */
        if (dr_path) {
                if ((resolved =
                     ib_resolve_portid_str_via(&portid, dr_path, IB_DEST_DRPATH,
                                               NULL, ibmad_port)) < 0)
-                       IBWARN("Failed to resolve %s; attempting full scan\n",
+                       IBWARN("Failed to resolve %s; attempting full scan",
                               dr_path);
        } else if (node_guid_str) {
                if ((resolved =
                     ib_resolve_portid_str_via(&portid, node_guid_str,
                                               IB_DEST_GUID, ibd_sm_id,
                                               ibmad_port)) < 0)
-                       IBWARN("Failed to resolve %s; attempting full scan\n",
+                       IBWARN("Failed to resolve %s; attempting full scan",
                               node_guid_str);
        }
 
-       if (resolved >= 0)
-               if ((fabric = ibnd_discover_fabric(ibmad_port, &portid,
-                                                  0)) == NULL)
-                       IBWARN
-                           ("Single node discover failed; attempting full scan\n");
-
-       if (!fabric)            /* do a full scan */
-               if ((fabric =
-                    ibnd_discover_fabric(ibmad_port, NULL, -1)) == NULL) {
+       if (load_cache_file) {
+               if ((fabric = ibnd_load_fabric(load_cache_file, 0)) == NULL) {
+                       fprintf(stderr, "loading cached fabric failed\n");
+                       exit(1);
+               }
+       } else {
+               if (resolved >= 0 &&
+                   !(fabric = ibnd_discover_fabric(ibd_ca, ibd_ca_port,
+                                                   &portid, &config)))
+                       IBWARN("Single node discover failed;"
+                              " attempting full scan");
+
+               if (!fabric && !(fabric = ibnd_discover_fabric(ibd_ca,
+                                                              ibd_ca_port,
+                                                              NULL,
+                                                              &config))) {
                        fprintf(stderr, "discover failed\n");
                        rc = 1;
                        goto close_port;
                }
+       }
 
        report_suppressed();
 
@@ -506,8 +664,10 @@ int main(int argc, char **argv)
                uint8_t ni[IB_SMP_DATA_SIZE];
 
                if (!smp_query_via(ni, &portid, IB_ATTR_NODE_INFO, 0,
-                                  ibd_timeout, ibmad_port))
-                       return -1;
+                                  ibd_timeout, ibmad_port)) {
+                       rc = -1;
+                       goto destroy_fabric;
+               }
                mad_decode_field(ni, IB_NODE_GUID_F, &(node_guid));
 
                node = ibnd_find_node_guid(fabric, node_guid);
@@ -518,6 +678,7 @@ int main(int argc, char **argv)
        } else
                ibnd_iter_nodes(fabric, print_node, NULL);
 
+destroy_fabric:
        ibnd_destroy_fabric(fabric);
 
 close_port:
index d1acafe8769a65a44c171759ec531321198f9909..75b9f903a75c6093be91550450f8aba6b0c53af7 100644 (file)
@@ -20,6 +20,7 @@ C_DEFINES = $(C_DEFINES) /DHAVE_CONFIG_H
 \r
 TARGETLIBS = \\r
        $(SDK_LIB_PATH)\kernel32.lib    \\r
+       $(SDK_LIB_PATH)\ws2_32.lib              \\r
 !if $(FREEBUILD)\r
        $(TARGETPATH)\*\complib.lib             \\r
        $(TARGETPATH)\*\libibmad.lib    \\r
index dd4858f700812565a5044a6f86df05181c83c89b..b765c847c450c4f89c330ba164c3c7915a55d02c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2008 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
  * Copyright (c) 2009 Mellanox Technologies LTD.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -142,7 +142,7 @@ char *dump_multicast_tables(ib_portid_t * portid, unsigned startlid,
        uint64_t nodeguid;
        uint32_t mod;
        unsigned block, i, j, e, nports, cap, chunks, startblock, lastblock,
-                top;
+           top;
        int n = 0;
 
        if ((s = check_switch(portid, &nports, &nodeguid, sw, nd)))
index 1de3d99397f5b9a576db53ff463a8c50a057a587..1b9159551660b83781115fe5549c78bcba5d164f 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2008 Lawrence Livermore National Security
- * Copyright (c) 2009 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2008-2009 Voltaire Inc.  All rights reserved.
  * Copyright (c) 2009 HNR Consulting.  All rights reserved.
  *
  * Produced at Lawrence Livermore National Laboratory.
@@ -73,6 +73,15 @@ static uint32_t get_cap_mask(ib_portid_t * port)
        return cap_mask;
 }
 
+static void build_trap145(ib_mad_notice_attr_t * n, ib_portid_t * port)
+{
+       n->generic_type = 0x80 | IB_NOTICE_TYPE_INFO;
+       n->g_or_v.generic.prod_type_lsb = cl_hton16(get_node_type(port));
+       n->g_or_v.generic.trap_num = cl_hton16(145);
+       n->issuer_lid = cl_hton16((uint16_t) port->lid);
+       n->data_details.ntc_145.new_sys_guid = cl_hton64(0x1234567812345678);
+}
+
 static void build_trap144_local(ib_mad_notice_attr_t * n, ib_portid_t * port)
 {
        n->generic_type = 0x80 | IB_NOTICE_TYPE_INFO;
@@ -149,6 +158,7 @@ static const trap_def_t traps[] = {
        {"node_desc_change", build_trap144_nodedesc},
        {"link_speed_enabled_change", build_trap144_linkspeed},
        {"local_link_integrity", build_trap129},
+       {"sys_image_guid_change", build_trap145},
        {NULL, NULL}
 };
 
index 9752de86e5fc8c5df761762a99590ae607447551..c44d8c4b9a893c22264bc43b1ed9ba8955bf546c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2008 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2004-2009 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
@@ -124,6 +124,7 @@ static int port_dump(umad_port_t * port, int alone)
        printf("%sCapability mask: 0x%08x\n", pre, ntohl(port->capmask));
        printf("%sPort GUID: 0x%016llx\n", pre,
               (long long unsigned)ntohll(port->port_guid));
+       printf("%sLink layer: %s\n", pre, port->link_layer);
        return 0;
 }
 
@@ -142,9 +143,8 @@ static int ca_stat(char *ca_name, int portnum, int no_ports)
                if (portnum > ca.numports || !ca.ports[portnum]) {
                        IBWARN("%s: '%s' has no port number %d - max (%d)",
                               ((unsigned)ca.node_type <=
-                               IB_NODE_MAX ? node_type_str[ca.
-                                                           node_type] : "???"),
-                              ca_name, portnum, ca.numports);
+                               IB_NODE_MAX ? node_type_str[ca.node_type] :
+                               "???"), ca_name, portnum, ca.numports);
                        return -1;
                }
                printf("%s: '%s'\n",
index e5f8f1b5c2188422ecd654597edddca4b8167371..f007aa3ea51ff5ea5dbdfb040559b0884ae4ab3e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2008 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2004-2009 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
index 92160c44e3c8e35070e86bc919384392c26f66eb..80694f2c6cf46d9d640e556c0d9c4f0b5b597fc7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2008 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
  * Copyright (c) 2009 HNR Consulting.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -659,17 +659,15 @@ static void dump_mcpath(Node * node, int dumplevel)
                        printf("[%d] -> %s {0x%016" PRIx64 "}[%d]\n",
                               node->ports->remoteport->portnum,
                               (node->type <=
-                               IB_NODE_MAX ? node_type_str[node->
-                                                           type] : "???"),
-                              node->nodeguid, node->upport);
+                               IB_NODE_MAX ? node_type_str[node->type] :
+                               "???"), node->nodeguid, node->upport);
                else
                        printf("[%d] -> %s 0x%" PRIx64 "[%d] lid %u \"%s\"\n",
                               node->ports->remoteport->portnum,
                               (node->type <=
-                               IB_NODE_MAX ? node_type_str[node->
-                                                           type] : "???"),
-                              node->nodeguid, node->upport, node->ports->lid,
-                              nodename);
+                               IB_NODE_MAX ? node_type_str[node->type] :
+                               "???"), node->nodeguid, node->upport,
+                              node->ports->lid, nodename);
        }
 
        if (node->dist < 0)
index dae1670370322005387f9325577b28f58601887f..a764d021ccb240674aa174bbdcc9ead5238f6e66 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2006-2009 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
index d70af9e74a1b0de1d4968f2ead2eaa4bbe65a654..07a922645d2843ddfc8f964e8031b1037dbfa7c8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2008 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
  * Copyright (c) 2007 Xsigo Systems Inc.  All rights reserved.
  * Copyright (c) 2009 HNR Consulting.  All rights reserved.
  *
@@ -293,8 +293,8 @@ static void dump_perfcounters(int extended, int timeout, uint16_t cap_mask,
                        IBERROR("perfquery");
                if (!(cap_mask & 0x1000)) {
                        /* if PortCounters:PortXmitWait not supported clear this counter */
-                       IBWARN
-                           ("PortXmitWait not indicated so ignore this counter");
+                       VERBOSE("PortXmitWait not indicated"
+                               " so ignore this counter");
                        perf_count.xmtwait = 0;
                        mad_encode_field(pc, IB_PC_XMT_WAIT_F,
                                         &perf_count.xmtwait);
@@ -302,7 +302,10 @@ static void dump_perfcounters(int extended, int timeout, uint16_t cap_mask,
                if (aggregate)
                        aggregate_perfcounters();
                else
-                       mad_dump_perfcounters(buf, sizeof buf, pc, sizeof pc);
+                       mad_dump_fields(buf, sizeof buf, pc, sizeof pc,
+                                                       IB_PC_FIRST_F,
+                                                       (cap_mask & 0x1000)?IB_PC_LAST_F:(IB_PC_RCV_PKTS_F+1));
+
        } else {
                if (!(cap_mask & 0x200))        /* 1.2 errata: bit 9 is extended counter support */
                        IBWARN
@@ -344,56 +347,70 @@ static void reset_counters(int extended, int timeout, int mask,
 }
 
 static int reset, reset_only, all_ports, loop_ports, port, extended, xmt_sl,
-    rcv_sl;
+    rcv_sl, xmt_disc, rcv_err, smpl_ctl;
 
-void xmt_sl_query(ib_portid_t * portid, int port, int mask)
+static void common_func(ib_portid_t * portid, int port_num, int mask,
+                       unsigned query, unsigned reset,
+                       const char *name, uint16_t attr,
+                       void dump_func(char *, int, void *, int))
 {
        char buf[1024];
 
-       if (reset_only) {
-               if (!performance_reset_via(pc, portid, port, mask, ibd_timeout,
-                                          IB_GSI_PORT_XMIT_DATA_SL, srcport))
-                       IBERROR("perfslreset");
-               return;
+       if (query) {
+               if (!pma_query_via(pc, portid, port_num, ibd_timeout, attr,
+                                  srcport))
+                       IBERROR("cannot query %s", name);
+
+               dump_func(buf, sizeof(buf), pc, sizeof(pc));
+
+               printf("# %s counters: %s port %d\n%s", name,
+                      portid2str(portid), port_num, buf);
        }
 
-       if (!pma_query_via(pc, portid, port, ibd_timeout,
-                          IB_GSI_PORT_XMIT_DATA_SL, srcport))
-               IBERROR("perfslquery");
+       if (reset && !performance_reset_via(pc, portid, port, mask, ibd_timeout,
+                                           attr, srcport))
+               IBERROR("cannot reset %s", name);
+}
 
-       mad_dump_perfcounters_xmt_sl(buf, sizeof buf, pc, sizeof pc);
-       printf("# PortXmitDataSL counters: %s port %d\n%s", portid2str(portid),
-              port, buf);
+static void xmt_sl_query(ib_portid_t * portid, int port, int mask)
+{
+       common_func(portid, port, mask, !reset_only, (reset_only || reset),
+                   "PortXmitDataSL", IB_GSI_PORT_XMIT_DATA_SL,
+                   mad_dump_perfcounters_xmt_sl);
+}
 
-       if (reset)
-               if (!performance_reset_via(pc, portid, port, mask, ibd_timeout,
-                                          IB_GSI_PORT_XMIT_DATA_SL, srcport))
-                       IBERROR("perfslreset");
+static void rcv_sl_query(ib_portid_t * portid, int port, int mask)
+{
+       common_func(portid, port, mask, !reset_only, (reset_only || reset),
+                   "PortRcvDataSL", IB_GSI_PORT_RCV_DATA_SL,
+                   mad_dump_perfcounters_rcv_sl);
 }
 
-void rcv_sl_query(ib_portid_t * portid, int port, int mask)
+static void xmt_disc_query(ib_portid_t * portid, int port, int mask)
 {
-       char buf[1024];
+       common_func(portid, port, mask, !reset_only, (reset_only || reset),
+                   "PortXmitDiscardDetails", IB_GSI_PORT_XMIT_DISCARD_DETAILS,
+                   mad_dump_perfcounters_xmt_disc);
+}
 
-       if (reset_only) {
-               if (!performance_reset_via(pc, portid, port, mask, ibd_timeout,
-                                          IB_GSI_PORT_RCV_DATA_SL, srcport))
-                       IBERROR("perfslreset");
-               return;
-       }
+static void rcv_err_query(ib_portid_t * portid, int port, int mask)
+{
+       common_func(portid, port, mask, !reset_only, (reset_only || reset),
+                   "PortRcvErrorDetails", IB_GSI_PORT_RCV_ERROR_DETAILS,
+                   mad_dump_perfcounters_rcv_err);
+}
+
+void dump_portsamples_control(ib_portid_t * portid, int port)
+{
+       char buf[1024];
 
        if (!pma_query_via(pc, portid, port, ibd_timeout,
-                          IB_GSI_PORT_RCV_DATA_SL, srcport))
-               IBERROR("perfslquery");
+                          IB_GSI_PORT_SAMPLES_CONTROL, srcport))
+               IBERROR("sampctlquery");
 
-       mad_dump_perfcounters_rcv_sl(buf, sizeof buf, pc, sizeof pc);
-       printf("# PortRcvDataSL counters: %s port %d\n%s", portid2str(portid),
+       mad_dump_portsamples_control(buf, sizeof buf, pc, sizeof pc);
+       printf("# PortSamplesControl: %s port %d\n%s", portid2str(portid),
               port, buf);
-
-       if (reset)
-               if (!performance_reset_via(pc, portid, port, mask, ibd_timeout,
-                                          IB_GSI_PORT_RCV_DATA_SL, srcport))
-                       IBERROR("perfslreset");
 }
 
 static int process_opt(void *context, int ch, char *optarg)
@@ -408,6 +425,15 @@ static int process_opt(void *context, int ch, char *optarg)
        case 'S':
                rcv_sl = 1;
                break;
+       case 'D':
+               xmt_disc = 1;
+               break;
+       case 'E':
+               rcv_err = 1;
+               break;
+       case 'c':
+               smpl_ctl = 1;
+               break;
        case 'a':
                all_ports++;
                port = ALL_PORTS;
@@ -446,6 +472,9 @@ int main(int argc, char **argv)
                {"extended", 'x', 0, NULL, "show extended port counters"},
                {"xmtsl", 'X', 0, NULL, "show Xmt SL port counters"},
                {"rcvsl", 'S', 0, NULL, "show Rcv SL port counters"},
+               {"xmtdisc", 'D', 0, NULL, "show Xmt Discard Details"},
+               {"rcverr", 'E', 0, NULL, "show Rcv Error Details"},
+               {"smplctl", 'c', 0, NULL, "show samples control"},
                {"all_ports", 'a', 0, NULL, "show aggregated counters"},
                {"loop_ports", 'l', 0, NULL, "iterate through each port"},
                {"reset_after_read", 'r', 0, NULL, "reset counters after read"},
@@ -516,6 +545,21 @@ int main(int argc, char **argv)
                goto done;
        }
 
+       if (xmt_disc) {
+               xmt_disc_query(&portid, port, mask);
+               goto done;
+       }
+
+       if (rcv_err) {
+               rcv_err_query(&portid, port, mask);
+               goto done;
+       }
+
+       if (smpl_ctl) {
+               dump_portsamples_control(&portid, port);
+               goto done;
+       }
+
        if (all_ports_loop || (loop_ports && (all_ports || port == ALL_PORTS))) {
                if (smp_query_via(data, &portid, IB_ATTR_NODE_INFO, 0, 0,
                                  srcport) < 0)
index d880261fa3bd4d12e1463fe4961c20d63a89f678..5e9a5ad10c2603d4c86babeb1028b5e3f5f7d949 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (c) 2006,2007 The Regents of the University of California.
- * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
  * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.
  * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
  * Copyright (c) 2009 HNR Consulting. All rights reserved.
@@ -124,6 +124,45 @@ int requested_lid_flag = 0;
 uint64_t requested_guid = 0;
 int requested_guid_flag = 0;
 
+#define SA_ERR_UNKNOWN IB_SA_MAD_STATUS_PRIO_SUGGESTED
+
+const char *ib_sa_error_str[] = {
+       "SA_NO_ERROR",
+       "SA_ERR_NO_RESOURCES",
+       "SA_ERR_REQ_INVALID",
+       "SA_ERR_NO_RECORDS",
+       "SA_ERR_TOO_MANY_RECORDS",
+       "SA_ERR_REQ_INVALID_GID",
+       "SA_ERR_REQ_INSUFFICIENT_COMPONENTS",
+       "SA_ERR_REQ_DENIED",
+       "SA_ERR_STATUS_PRIO_SUGGESTED",
+       "SA_ERR_UNKNOWN"
+};
+
+static inline const char *ib_sa_err_str(IN uint8_t status)
+{
+       if (status > SA_ERR_UNKNOWN)
+               status = SA_ERR_UNKNOWN;
+       return (ib_sa_error_str[status]);
+}
+
+static inline void report_err(int status)
+{
+       int st = status & 0xff;
+       char sm_err_str[64] = { 0 };
+       char sa_err_str[64] = { 0 };
+
+       if (st)
+               sprintf(sm_err_str, " SM(%s)", ib_get_err_str(st));
+
+       st = status >> 8;
+       if (st)
+               sprintf(sa_err_str, " SA(%s)", ib_sa_err_str((uint8_t) st));
+
+       fprintf(stderr, "ERROR: Query result returned 0x%04x, %s%s\n",
+               status, sm_err_str, sa_err_str);
+}
+
 static int sa_query(struct bind_handle *h, uint8_t method,
                    uint16_t attr, uint32_t mod, uint64_t comp_mask,
                    uint64_t sm_key, void *data)
@@ -240,14 +279,14 @@ static void dump_node_record(void *data)
               "\t\tbase_version............0x%X\n"
               "\t\tclass_version...........0x%X\n"
               "\t\tnode_type...............%s\n"
-              "\t\tnum_ports...............0x%X\n"
+              "\t\tnum_ports...............%u\n"
               "\t\tsys_guid................0x%016" PRIx64 "\n"
               "\t\tnode_guid...............0x%016" PRIx64 "\n"
               "\t\tport_guid...............0x%016" PRIx64 "\n"
               "\t\tpartition_cap...........0x%X\n"
               "\t\tdevice_id...............0x%X\n"
               "\t\trevision................0x%X\n"
-              "\t\tport_num................0x%X\n"
+              "\t\tport_num................%u\n"
               "\t\tvendor_id...............0x%X\n"
               "\t\tNodeDescription.........%s\n",
               cl_ntoh16(nr->lid), cl_ntoh16(nr->resv),
@@ -300,8 +339,8 @@ static void dump_path_record(void *data)
               "\t\tservice_id..............0x%016" PRIx64 "\n"
               "\t\tdgid....................%s\n"
               "\t\tsgid....................%s\n"
-              "\t\tdlid....................0x%X\n"
-              "\t\tslid....................0x%X\n"
+              "\t\tdlid....................%u\n"
+              "\t\tslid....................%u\n"
               "\t\thop_flow_raw............0x%X\n"
               "\t\ttclass..................0x%X\n"
               "\t\tnum_path_revers.........0x%X\n"
@@ -312,8 +351,7 @@ static void dump_path_record(void *data)
               "\t\trate....................0x%X\n"
               "\t\tpkt_life................0x%X\n"
               "\t\tpreference..............0x%X\n"
-              "\t\tresv2...................0x%X\n"
-              "\t\tresv3...................0x%X\n",
+              "\t\tresv2...................0x%02X%02X%02X%02X%02X%02X\n",
               cl_ntoh64(p_pr->service_id),
               inet_ntop(AF_INET6, p_pr->dgid.raw, gid_str, sizeof gid_str),
               inet_ntop(AF_INET6, p_pr->sgid.raw, gid_str2, sizeof gid_str2),
@@ -322,7 +360,8 @@ static void dump_path_record(void *data)
               cl_ntoh16(p_pr->pkey), ib_path_rec_qos_class(p_pr),
               ib_path_rec_sl(p_pr), p_pr->mtu, p_pr->rate, p_pr->pkt_life,
               p_pr->preference,
-              *(uint32_t *) & p_pr->resv2, *((uint16_t *) & p_pr->resv2 + 2));
+              p_pr->resv2[0], p_pr->resv2[1], p_pr->resv2[2],
+              p_pr->resv2[3], p_pr->resv2[4], p_pr->resv2[5]);
 }
 
 static void dump_class_port_info(void *data)
@@ -368,9 +407,9 @@ static void dump_portinfo_record(void *data)
 
        printf("PortInfoRecord dump:\n"
               "\t\tEndPortLid..............%u\n"
-              "\t\tPortNum.................0x%X\n"
-              "\t\tbase_lid................0x%X\n"
-              "\t\tmaster_sm_base_lid......0x%X\n"
+              "\t\tPortNum.................%u\n"
+              "\t\tbase_lid................%u\n"
+              "\t\tmaster_sm_base_lid......%u\n"
               "\t\tcapability_mask.........0x%X\n",
               cl_ntoh16(p_pir->lid), p_pir->port_num,
               cl_ntoh16(p_pi->base_lid), cl_ntoh16(p_pi->master_sm_base_lid),
@@ -388,7 +427,7 @@ static void dump_one_portinfo_record(void *data)
        printf("PortInfoRecord dump:\n"
               "\tRID:\n"
               "\t\tEndPortLid..............%u\n"
-              "\t\tPortNum.................0x%x\n"
+              "\t\tPortNum.................%u\n"
               "\t\tReserved................0x%x\n"
               "\tPortInfo dump:\n\t\t%s",
               cl_ntoh16(pir->lid), pir->port_num, pir->resv, buf2);
@@ -581,8 +620,8 @@ static void dump_inform_info_record(void *data)
        uint32_t qpn;
        uint8_t resp_time_val;
 
-       ib_inform_info_get_qpn_resp_time(p_iir->inform_info.g_or_v.generic.
-                                        qpn_resp_time_val, &qpn,
+       ib_inform_info_get_qpn_resp_time(p_iir->inform_info.g_or_v.
+                                        generic.qpn_resp_time_val, &qpn,
                                         &resp_time_val);
        if (p_iir->inform_info.is_generic)
                printf("InformInfoRecord dump:\n"
@@ -591,8 +630,8 @@ static void dump_inform_info_record(void *data)
                       "\t\tSubscriberEnum..........0x%X\n"
                       "\t\tInformInfo dump:\n"
                       "\t\tgid.....................%s\n"
-                      "\t\tlid_range_begin.........0x%X\n"
-                      "\t\tlid_range_end...........0x%X\n"
+                      "\t\tlid_range_begin.........%u\n"
+                      "\t\tlid_range_end...........%u\n"
                       "\t\tis_generic..............0x%X\n"
                       "\t\tsubscribe...............0x%X\n"
                       "\t\ttrap_type...............0x%X\n"
@@ -621,8 +660,8 @@ static void dump_inform_info_record(void *data)
                       "\t\tSubscriberEnum..........0x%X\n"
                       "\t\tInformInfo dump:\n"
                       "\t\tgid.....................%s\n"
-                      "\t\tlid_range_begin.........0x%X\n"
-                      "\t\tlid_range_end...........0x%X\n"
+                      "\t\tlid_range_begin.........%u\n"
+                      "\t\tlid_range_end...........%u\n"
                       "\t\tis_generic..............0x%X\n"
                       "\t\tsubscribe...............0x%X\n"
                       "\t\ttrap_type...............0x%X\n"
@@ -794,8 +833,7 @@ static int get_any_records(bind_handle_t h,
        }
 
        if (result.status != IB_SUCCESS) {
-               fprintf(stderr, "Query result returned: %s\n",
-                       ib_get_err_str(result.status));
+               report_err(result.status);
                return result.status;
        }
 
@@ -985,8 +1023,8 @@ static int print_node_records(bind_handle_t h)
                        if (!requested_name ||
                            (strncmp(requested_name,
                                     (char *)node_record->node_desc.description,
-                                    sizeof(node_record->node_desc.
-                                           description)) == 0)) {
+                                    sizeof(node_record->
+                                           node_desc.description)) == 0)) {
                                print_node_record(node_record);
                                if (node_print_desc == UNIQUE_LID_ONLY) {
                                        return_mad();
@@ -1009,8 +1047,7 @@ static int get_print_class_port_info(bind_handle_t h)
                return ret;
        }
        if (result.status != IB_SUCCESS) {
-               fprintf(stderr, "ERROR: Query result returned: %s\n",
-                       ib_get_err_str(result.status));
+               report_err(result.status);
                return (result.status);
        }
        dump_results(&result, dump_class_port_info);
index 77495f9f9524823a2d32550bf3c093f7e5f6c4cc..ef13911503da2edbb6924b7bf47658278defbf56 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2008 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2004-2009 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
index a4f427d90c95b2f9c3c594527eb763eb7c7aa1c0..a6c4dfa327fadef94ae77b2891ef1f2241503c33 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2008 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2004-2009 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
index 95b269e4afbd1086807d0f32a81348875c9386ca..a1559e88a74e622cbf7b8b8e3e7a918ed0468093 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2008 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2004-2009 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
index 23375dd132b067f0b420b925b99689cd8fdd6240..92a90c8fc9bcfd0e704cb7726b4ba09bd8467c99 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2008 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2004-2009 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
@@ -96,15 +96,13 @@ typedef struct {
        is3_sw_info_t sw_info;
 } is3_general_info_t;
 
-typedef struct {
-       uint32_t address;
-       uint32_t data;
-       uint32_t mask;
-} is3_record_t;
-
 typedef struct {
        uint8_t reserved[8];
-       is3_record_t record[18];
+       struct is3_record {
+               uint32_t address;
+               uint32_t data;
+               uint32_t mask;
+       } record[18];
 } is3_config_space_t;
 
 #define COUNTER_GROUPS_NUM 2
@@ -127,23 +125,61 @@ typedef struct {
        is4_group_select_t group_selects[COUNTER_GROUPS_NUM];
 } is4_config_counter_groups_t;
 
-void counter_groups_info(ib_portid_t * portid, int port)
+static int do_vendor(ib_portid_t *portid, struct ibmad_port *srcport,
+                    uint8_t class, uint8_t method, uint16_t attr_id,
+                    uint32_t attr_mod, void *data)
 {
-       char buf[1024];
        ib_vendor_call_t call;
-       is4_counter_group_info_t *cg_info;
-       int i, num_cg;
 
        memset(&call, 0, sizeof(call));
-       call.mgmt_class = IB_MLX_VENDOR_CLASS;
-       call.method = IB_MAD_METHOD_GET;
+       call.mgmt_class = class;
+       call.method = method;
        call.timeout = ibd_timeout;
-       call.attrid = IB_MLX_IS4_COUNTER_GROUP_INFO;
-       call.mod = port;
+       call.attrid = attr_id;
+       call.mod = attr_mod;
+
+       if (!ib_vendor_call_via(data, portid, &call, srcport))
+               IBERROR("vendstat: method %u, attribute %u", method, attr_id);
+
+       return 0;
+}
+
+static void do_config_space_records(ib_portid_t *portid, unsigned set,
+                                   is3_config_space_t *cs, unsigned records)
+{
+       unsigned i;
+
+       if (records > 18)
+               records = 18;
+       for (i = 0; i < records; i++) {
+               cs->record[i].address = htonl(cs->record[i].address);
+               cs->record[i].data = htonl(cs->record[i].data);
+               cs->record[i].mask = htonl(cs->record[i].mask);
+       }
+
+       if (do_vendor(portid, srcport, IB_MLX_VENDOR_CLASS,
+                     set ? IB_MAD_METHOD_SET : IB_MAD_METHOD_GET,
+                     IB_MLX_IS3_CONFIG_SPACE_ACCESS, 2 << 22 | records << 16,
+                     cs))
+               IBERROR("cannot %s config space records", set ? "set" : "get");
+
+       for (i = 0; i < records; i++) {
+               printf("Config space record at 0x%x: 0x%x\n",
+                      ntohl(cs->record[i].address),
+                      ntohl(cs->record[i].data & cs->record[i].mask));
+       }
+}
+
+static void counter_groups_info(ib_portid_t * portid, int port)
+{
+       char buf[1024];
+       is4_counter_group_info_t *cg_info;
+       int i, num_cg;
 
        /* Counter Group Info */
        memset(&buf, 0, sizeof(buf));
-       if (!ib_vendor_call_via(&buf, portid, &call, srcport))
+       if (do_vendor(portid, srcport, IB_MLX_VENDOR_CLASS, IB_MAD_METHOD_GET,
+                     IB_MLX_IS4_COUNTER_GROUP_INFO, port, buf))
                IBERROR("counter group info query");
 
        cg_info = (is4_counter_group_info_t *) & buf;
@@ -166,20 +202,12 @@ void counter_groups_info(ib_portid_t * portid, int port)
 
 static int cg0, cg1;
 
-void config_counter_groups(ib_portid_t * portid, int port)
+static void config_counter_groups(ib_portid_t * portid, int port)
 {
        char buf[1024];
-       ib_vendor_call_t call;
        is4_config_counter_groups_t *cg_config;
 
-       memset(&call, 0, sizeof(call));
-       call.mgmt_class = IB_MLX_VENDOR_CLASS;
-       call.attrid = IB_MLX_IS4_CONFIG_COUNTER_GROUP;
-       call.timeout = ibd_timeout;
-       call.mod = port;
        /* configure counter groups for groups 0 and 1 */
-       call.method = IB_MAD_METHOD_SET;
-
        memset(&buf, 0, sizeof(buf));
        cg_config = (is4_config_counter_groups_t *) & buf;
 
@@ -188,18 +216,22 @@ void config_counter_groups(ib_portid_t * portid, int port)
        cg_config->group_selects[0].group_select = (uint8_t) cg0;
        cg_config->group_selects[1].group_select = (uint8_t) cg1;
 
-       if (!ib_vendor_call_via(&buf, portid, &call, srcport))
+       if (do_vendor(portid, srcport, IB_MLX_VENDOR_CLASS, IB_MAD_METHOD_SET,
+                     IB_MLX_IS4_CONFIG_COUNTER_GROUP, port, buf))
                IBERROR("config counter group set");
 
        /* get config counter groups */
        memset(&buf, 0, sizeof(buf));
-       call.method = IB_MAD_METHOD_GET;
 
-       if (!ib_vendor_call_via(&buf, portid, &call, srcport))
+       if (do_vendor(portid, srcport, IB_MLX_VENDOR_CLASS, IB_MAD_METHOD_GET,
+                     IB_MLX_IS4_CONFIG_COUNTER_GROUP, port, buf))
                IBERROR("config counter group query");
 }
 
 static int general_info, xmit_wait, counter_group_info, config_counter_group;
+static is3_config_space_t write_cs, read_cs;
+static unsigned write_cs_records, read_cs_records;
+
 
 static int process_opt(void *context, int ch, char *optarg)
 {
@@ -220,6 +252,31 @@ static int process_opt(void *context, int ch, char *optarg)
                if (ret != 2)
                        return -1;
                break;
+       case 'R':
+               if (read_cs_records >= 18)
+                       break;
+               ret = sscanf(optarg, "%x,%x",
+                            &read_cs.record[read_cs_records].address,
+                            &read_cs.record[read_cs_records].mask);
+               if (ret < 1)
+                       return -1;
+               else if (ret == 1)
+                       read_cs.record[read_cs_records].mask = 0xffffffff;
+               read_cs_records++;
+               break;
+       case 'W':
+               if (write_cs_records >= 18)
+                       break;
+               ret = sscanf(optarg, "%x,%x,%x",
+                            &write_cs.record[write_cs_records].address,
+                            &write_cs.record[write_cs_records].data,
+                            &write_cs.record[write_cs_records].mask);
+               if (ret < 2)
+                       return -1;
+               else if (ret == 2)
+                       write_cs.record[write_cs_records].mask = 0xffffffff;
+               write_cs_records++;
+               break;
        default:
                return -1;
        }
@@ -234,22 +291,21 @@ int main(int argc, char **argv)
        ib_portid_t portid = { 0 };
        int port = 0;
        char buf[1024];
-       ib_vendor_call_t call;
        is3_general_info_t *gi;
-       is3_config_space_t *cs;
-       int i;
 
        const struct ibdiag_opt opts[] = {
-               {"N", 'N', 0, NULL, "show IS3 general information"},
+               {"N", 'N', 0, NULL, "show IS3 or IS4 general information"},
                {"w", 'w', 0, NULL, "show IS3 port xmit wait counters"},
                {"i", 'i', 0, NULL, "show IS4 counter group info"},
                {"c", 'c', 1, "<num,num>", "configure IS4 counter groups"},
+               {"Read", 'R', 1, "<addr,mask>", "Read configuration space record at addr"},
+               {"Write", 'W', 1, "<addr,val,mask>", "Write configuration space record at addr"},
                {0}
        };
 
        char usage_args[] = "<lid|guid> [port]";
        const char *usage_examples[] = {
-               "-N 6\t\t# read IS3 general information",
+               "-N 6\t\t# read IS3 or IS4 general information",
                "-w 6\t\t# read IS3 port xmit wait counters",
                "-i 6 12\t# read IS4 port 12 counter group info",
                "-c 0,1 6 12\t# configure IS4 port 12 counter groups for PortXmitDataSL",
@@ -289,6 +345,16 @@ int main(int argc, char **argv)
                exit(0);
        }
 
+       if (read_cs_records || write_cs_records) {
+               if (read_cs_records)
+                       do_config_space_records(&portid, 0, &read_cs,
+                                               read_cs_records);
+               if (write_cs_records)
+                       do_config_space_records(&portid, 1, &write_cs,
+                                               write_cs_records);
+               exit(0);
+       }
+
        /* These are Mellanox specific vendor MADs */
        /* but vendors change the VendorId so how know for sure ? */
        /* Only General Info and Port Xmit Wait Counters */
@@ -299,25 +365,19 @@ int main(int argc, char **argv)
        /* Would need a list of these and it might not be complete */
        /* so for right now, punt on this */
 
-       memset(&call, 0, sizeof(call));
-       call.mgmt_class = IB_MLX_VENDOR_CLASS;
-       call.method = IB_MAD_METHOD_GET;
-       call.timeout = ibd_timeout;
-
-       memset(&buf, 0, sizeof(buf));
        /* vendor ClassPortInfo is required attribute if class supported */
-       call.attrid = CLASS_PORT_INFO;
-       if (!ib_vendor_call_via(&buf, &portid, &call, srcport))
+       memset(&buf, 0, sizeof(buf));
+       if (do_vendor(&portid, srcport, IB_MLX_VENDOR_CLASS, IB_MAD_METHOD_GET,
+                     CLASS_PORT_INFO, 0, buf))
                IBERROR("classportinfo query");
 
        memset(&buf, 0, sizeof(buf));
-       call.attrid = IB_MLX_IS3_GENERAL_INFO;
-       if (!ib_vendor_call_via(&buf, &portid, &call, srcport))
-               IBERROR("vendstat");
        gi = (is3_general_info_t *) & buf;
+       if (do_vendor(&portid, srcport, IB_MLX_VENDOR_CLASS, IB_MAD_METHOD_GET,
+                     IB_MLX_IS3_GENERAL_INFO, 0, gi))
 
        if (general_info) {
-               /* dump IS3 general info here */
+               /* dump IS3 or IS4 general info here */
                printf("hw_dev_rev:  0x%04x\n", ntohs(gi->hw_info.hw_revision));
                printf("hw_dev_id:   0x%04x\n", ntohs(gi->hw_info.device_id));
                printf("hw_uptime:   0x%08x\n", ntohl(gi->hw_info.uptime));
@@ -336,20 +396,22 @@ int main(int argc, char **argv)
        }
 
        if (xmit_wait) {
+               is3_config_space_t *cs;
+               unsigned i;
+
                if (ntohs(gi->hw_info.device_id) != IS3_DEVICE_ID)
                        IBERROR("Unsupported device ID 0x%x",
                                ntohs(gi->hw_info.device_id));
 
                memset(&buf, 0, sizeof(buf));
-               call.attrid = IB_MLX_IS3_CONFIG_SPACE_ACCESS;
-               /* Limit of 18 accesses per MAD ? */
-               call.mod = 2 << 22 | 16 << 16;  /* 16 records */
                /* Set record addresses for each port */
                cs = (is3_config_space_t *) & buf;
                for (i = 0; i < 16; i++)
                        cs->record[i].address =
                            htonl(IB_MLX_IS3_PORT_XMIT_WAIT + ((i + 1) << 12));
-               if (!ib_vendor_call_via(&buf, &portid, &call, srcport))
+               if (do_vendor(&portid, srcport, IB_MLX_VENDOR_CLASS,
+                             IB_MAD_METHOD_GET, IB_MLX_IS3_CONFIG_SPACE_ACCESS,
+                             2 << 22 | 16 << 16, cs))
                        IBERROR("vendstat");
 
                for (i = 0; i < 16; i++)
@@ -358,14 +420,14 @@ int main(int argc, char **argv)
 
                /* Last 8 ports is another query */
                memset(&buf, 0, sizeof(buf));
-               call.attrid = IB_MLX_IS3_CONFIG_SPACE_ACCESS;
-               call.mod = 2 << 22 | 8 << 16;   /* 8 records */
                /* Set record addresses for each port */
                cs = (is3_config_space_t *) & buf;
                for (i = 0; i < 8; i++)
                        cs->record[i].address =
                            htonl(IB_MLX_IS3_PORT_XMIT_WAIT + ((i + 17) << 12));
-               if (!ib_vendor_call_via(&buf, &portid, &call, srcport))
+               if (do_vendor(&portid, srcport, IB_MLX_VENDOR_CLASS,
+                             IB_MAD_METHOD_GET, IB_MLX_IS3_CONFIG_SPACE_ACCESS,
+                             2 << 22 | 8 << 16, cs))
                        IBERROR("vendstat");
 
                for (i = 0; i < 8; i++)
index 94b64cf23dd8df312ff2866b5eb732d193e2f006..7571a619aab687e09e97403b0143bffa08895425 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2007 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
  * Copyright (c) 2009 HNR Consulting.  All rights reserved.
  * Copyright (c) 2009 Mellanox Technologies LTD.  All rights reserved.
  *
@@ -168,6 +168,8 @@ enum GSI_ATTR_ID {
        IB_GSI_PORT_SAMPLES_CONTROL = 0x10,
        IB_GSI_PORT_SAMPLES_RESULT = 0x11,
        IB_GSI_PORT_COUNTERS = 0x12,
+       IB_GSI_PORT_RCV_ERROR_DETAILS = 0x15,
+       IB_GSI_PORT_XMIT_DISCARD_DETAILS = 0x16,
        IB_GSI_PORT_COUNTERS_EXT = 0x1D,
        IB_GSI_PORT_XMIT_DATA_SL = 0x36,
        IB_GSI_PORT_RCV_DATA_SL = 0x37,
@@ -356,6 +358,7 @@ enum MAD_FIELDS {
        IB_PORT_QKEY_VIOL_F,
        IB_PORT_GUID_CAP_F,
        IB_PORT_CLIENT_REREG_F,
+       IB_PORT_MCAST_PKEY_SUPR_ENAB_F,
        IB_PORT_SUBN_TIMEOUT_F,
        IB_PORT_RESP_TIME_VAL_F,
        IB_PORT_LOCAL_PHYS_ERR_F,
@@ -604,6 +607,9 @@ enum MAD_FIELDS {
        IB_CPI_TRAP_QP_F,
        IB_CPI_TRAP_QKEY_F,
 
+       /*
+        * PortXmitDataSL fields
+        */
        IB_PC_XMT_DATA_SL_FIRST_F,
        IB_PC_XMT_DATA_SL0_F = IB_PC_XMT_DATA_SL_FIRST_F,
        IB_PC_XMT_DATA_SL1_F,
@@ -623,6 +629,9 @@ enum MAD_FIELDS {
        IB_PC_XMT_DATA_SL15_F,
        IB_PC_XMT_DATA_SL_LAST_F,
 
+       /*
+        * PortRcvDataSL fields
+        */
        IB_PC_RCV_DATA_SL_FIRST_F,
        IB_PC_RCV_DATA_SL0_F = IB_PC_RCV_DATA_SL_FIRST_F,
        IB_PC_RCV_DATA_SL1_F,
@@ -642,6 +651,61 @@ enum MAD_FIELDS {
        IB_PC_RCV_DATA_SL15_F,
        IB_PC_RCV_DATA_SL_LAST_F,
 
+       /*
+        * PortXmitDiscardDetails fields
+        */
+       IB_PC_XMT_INACT_DISC_F,
+       IB_PC_XMT_NEIGH_MTU_DISC_F,
+       IB_PC_XMT_SW_LIFE_DISC_F,
+       IB_PC_XMT_SW_HOL_DISC_F,
+       IB_PC_XMT_DISC_LAST_F,
+
+       /*
+        * PortRcvErrorDetails fields
+        */
+       IB_PC_RCV_LOCAL_PHY_ERR_F,
+       IB_PC_RCV_MALFORMED_PKT_ERR_F,
+       IB_PC_RCV_BUF_OVR_ERR_F,
+       IB_PC_RCV_DLID_MAP_ERR_F,
+       IB_PC_RCV_VL_MAP_ERR_F,
+       IB_PC_RCV_LOOPING_ERR_F,
+       IB_PC_RCV_ERR_LAST_F,
+
+       /*
+        * PortSamplesControl fields
+        */
+       IB_PSC_OPCODE_F,
+       IB_PSC_PORT_SELECT_F,
+       IB_PSC_TICK_F,
+       IB_PSC_COUNTER_WIDTH_F,
+       IB_PSC_COUNTER_MASK0_F,
+       IB_PSC_COUNTER_MASKS1TO9_F,
+       IB_PSC_COUNTER_MASKS10TO14_F,
+       IB_PSC_SAMPLE_MECHS_F,
+       IB_PSC_SAMPLE_STATUS_F,
+       IB_PSC_OPTION_MASK_F,
+       IB_PSC_VENDOR_MASK_F,
+       IB_PSC_SAMPLE_START_F,
+       IB_PSC_SAMPLE_INTVL_F,
+       IB_PSC_TAG_F,
+       IB_PSC_COUNTER_SEL0_F,
+       IB_PSC_COUNTER_SEL1_F,
+       IB_PSC_COUNTER_SEL2_F,
+       IB_PSC_COUNTER_SEL3_F,
+       IB_PSC_COUNTER_SEL4_F,
+       IB_PSC_COUNTER_SEL5_F,
+       IB_PSC_COUNTER_SEL6_F,
+       IB_PSC_COUNTER_SEL7_F,
+       IB_PSC_COUNTER_SEL8_F,
+       IB_PSC_COUNTER_SEL9_F,
+       IB_PSC_COUNTER_SEL10_F,
+       IB_PSC_COUNTER_SEL11_F,
+       IB_PSC_COUNTER_SEL12_F,
+       IB_PSC_COUNTER_SEL13_F,
+       IB_PSC_COUNTER_SEL14_F,
+       IB_PSC_SAMPLES_ONLY_OPT_MASK_F,
+       IB_PSC_LAST_F,
+
        IB_FIELD_LAST_          /* must be last */
 };
 
@@ -963,9 +1027,14 @@ MAD_EXPORT ib_mad_dump_fn
     mad_dump_node_type, mad_dump_sltovl, mad_dump_vlarbitration,
     mad_dump_nodedesc, mad_dump_nodeinfo, mad_dump_portinfo,
     mad_dump_switchinfo, mad_dump_perfcounters, mad_dump_perfcounters_ext,
-    mad_dump_perfcounters_xmt_sl, mad_dump_perfcounters_rcv_sl;
+    mad_dump_perfcounters_xmt_sl, mad_dump_perfcounters_rcv_sl,
+    mad_dump_perfcounters_xmt_disc, mad_dump_perfcounters_rcv_err,
+    mad_dump_portsamples_control;
+
+MAD_EXPORT void mad_dump_fields(char *buf, int bufsz, void *val, int valsz,
+                               int start, int end);
 
-MAD_EXPORT int ibdebug;
+extern MAD_EXPORT int ibdebug;
 
 #if __BYTE_ORDER == __LITTLE_ENDIAN
 #ifndef ntohll
@@ -1000,11 +1069,14 @@ static inline uint64_t htonll(uint64_t x)
 #define ALIGN(l, size) (((l) + ((size) - 1)) / (size) * (size))
 
 /** printf style warning MACRO, includes name of function and pid */
-#define IBWARN(fmt, ...) fprintf(stdout, "ibwarn: [%d] %s: " fmt "\n", getpid(), __func__, ## __VA_ARGS__)
+#define IBWARN(fmt, ...) fprintf(stderr, "ibwarn: [%d] %s: " fmt "\n", getpid(), __func__, ## __VA_ARGS__)
+
+#define IBDEBUG(fmt, ...) fprintf(stdout, "ibdebug: [%d] %s: " fmt "\n", getpid(), __func__, ## __VA_ARGS__)
+
+#define IBVERBOSE(fmt, ...) fprintf(stdout, "[%d] %s: " fmt "\n", getpid(), __func__, ## __VA_ARGS__)
 
-/** printf style abort MACRO, includes name of function and pid */
 #define IBPANIC(fmt, ...) do { \
-       fprintf(stdout, "ibpanic: [%d] %s: " fmt ": %m\n", getpid(), __func__, ## __VA_ARGS__); \
+       fprintf(stderr, "ibpanic: [%d] %s: " fmt ": %m\n", getpid(), __func__, ## __VA_ARGS__); \
        exit(-1); \
 } while(0)
 
index dff3a79e8c7523733e9bee386927d9c220e154c0..faabaecd971e58562b1bd5b1b84322d58591e1de 100644 (file)
@@ -46,7 +46,12 @@ typedef unsigned __int64     uint64_t;
 #define PRIo64 "I64o"\r
 #define PRIu64 "I64u"\r
 \r
-#define MAD_EXPORT     __declspec(dllexport)\r
+#ifndef MAD_EXPORT\r
+#define MAD_EXPORT     __declspec(dllimport)\r
+#endif\r
+#ifndef IBND_EXPORT\r
+#define IBND_EXPORT    __declspec(dllimport)\r
+#endif\r
 \r
 #define DEPRECATED\r
 \r
diff --git a/trunk/ulp/libibmad/include/windows/config.h b/trunk/ulp/libibmad/include/windows/config.h
new file mode 100644 (file)
index 0000000..129ca4f
--- /dev/null
@@ -0,0 +1,39 @@
+/*\r
+ * Copyright (c) 2010 Intel Corp, Inc.  All rights reserved.\r
+ *\r
+ * This software is available to you under a choice of one of two\r
+ * licenses.  You may choose to be licensed under the terms of the GNU\r
+ * General Public License (GPL) Version 2, available from the file\r
+ * COPYING in the main directory of this source tree, or the\r
+ * OpenIB.org BSD license below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ */\r
+\r
+#ifndef _CONFIG_H_\r
+#define _CONFIG_H_\r
+\r
+#define MAD_EXPORT     __declspec(dllexport)\r
+\r
+#endif /* _CONFIG_H_ */\r
index 3eeca40c597350111cd348a340000eb609b2dba3..e7634bb653908c853eea095b2162ddc464fc2c9f 100644 (file)
@@ -29,7 +29,7 @@ SOURCES = \
        vendor.c\r
        \r
 INCLUDES =     ..\include\infiniband;\\r
-                       ..\include;\\r
+                       ..\include;..\include\windows;\\r
                        ..\..\libibverbs\include;\\r
                        ..\..\libibumad\include;\\r
                        ..\..\..\inc;\\r
@@ -37,6 +37,7 @@ INCLUDES =    ..\include\infiniband;\
                        ..\..\..\inc\user\linux;\r
 \r
 USER_C_FLAGS = $(USER_C_FLAGS) -DEXPORT_IBMAD_SYMBOLS\r
+C_DEFINES = $(C_DEFINES) /DHAVE_CONFIG_H\r
 \r
 TARGETLIBS = \\r
        $(SDK_LIB_PATH)\kernel32.lib    \\r
index 2983855407f04dc2d26562638ecdbe28175c701f..318145120efc6115f7f58dcadae9526f0d9be7ba 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2007 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2004-2009 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
@@ -53,7 +53,11 @@ uint8_t *bm_call_via(void *data, ib_portid_t * portid, ib_bm_call_t * call,
 {
        ib_rpc_t rpc = { 0 };
        int resp_expected;
-       char data_with_bkey[IB_BM_BKEY_AND_DATA_SZ] = { 0 };
+       struct {
+               uint64_t bkey;
+               uint8_t reserved[32];
+               uint8_t data[IB_BM_DATA_SZ];
+       } bm_data;
 
        DEBUG("route %s data %p", portid2str(portid), data);
        if (portid->lid <= 0) {
@@ -74,9 +78,9 @@ uint8_t *bm_call_via(void *data, ib_portid_t * portid, ib_bm_call_t * call,
        rpc.dataoffs = IB_BM_BKEY_OFFS;
 
        // copy data to a buffer which also includes the bkey
-       *((uint64_t *) data_with_bkey) = htonll(call->bkey);
-       memcpy(data_with_bkey + IB_BM_DATA_OFFS - IB_BM_BKEY_OFFS, data,
-              IB_BM_DATA_SZ);
+       bm_data.bkey = htonll(call->bkey);
+       memset(bm_data.reserved, 0, sizeof(bm_data.reserved));
+       memcpy(bm_data.data, data, IB_BM_DATA_SZ);
 
        DEBUG
            ("method 0x%x attr 0x%x mod 0x%x datasz %d off %d res_ex %d bkey 0x%08x%08x",
@@ -89,17 +93,15 @@ uint8_t *bm_call_via(void *data, ib_portid_t * portid, ib_bm_call_t * call,
 
        if (resp_expected) {
                /* FIXME: no RMPP for now */
-               if (mad_rpc
-                   (srcport, &rpc, portid, data_with_bkey, data_with_bkey))
+               if (mad_rpc(srcport, &rpc, portid, &bm_data, &bm_data))
                        goto return_ok;
                return NULL;
        }
 
-       if (mad_send_via(&rpc, portid, 0, data_with_bkey, srcport) < 0)
+       if (mad_send_via(&rpc, portid, 0, &bm_data, srcport) < 0)
                return NULL;
 
 return_ok:
-       memcpy(data, data_with_bkey + IB_BM_DATA_OFFS - IB_BM_BKEY_OFFS,
-              IB_BM_DATA_SZ);
+       memcpy(data, bm_data.data, IB_BM_DATA_SZ);
        return data;
 }
index 5151882740635eeeba8571a7ba6c474299205934..c29f625bc480716a015b3cab973f223da83593e9 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2008 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
  * Copyright (c) 2007 Xsigo Systems Inc.  All rights reserved.
  * Copyright (c) 2009 Mellanox Technologies LTD.  All rights reserved.
  * Copyright (c) 2009 HNR Consulting.  All rights reserved.
@@ -671,6 +671,12 @@ static int _dump_fields(char *buf, int bufsz, void *data, int start, int end)
        return (int)(s - buf);
 }
 
+void mad_dump_fields(char *buf, int bufsz, void *val, int valsz, int start,
+                    int end)
+{
+       _dump_fields(buf, bufsz, val, start, end);
+}
+
 void mad_dump_nodedesc(char *buf, int bufsz, void *val, int valsz)
 {
        strncpy(buf, val, bufsz);
@@ -729,6 +735,31 @@ void mad_dump_perfcounters_rcv_sl(char *buf, int bufsz, void *val, int valsz)
                     IB_PC_RCV_DATA_SL_LAST_F);
 }
 
+void mad_dump_perfcounters_xmt_disc(char *buf, int bufsz, void *val, int valsz)
+{
+       int cnt;
+
+       cnt = _dump_fields(buf, bufsz, val, IB_PC_EXT_PORT_SELECT_F,
+                          IB_PC_EXT_XMT_BYTES_F);
+       _dump_fields(buf + cnt, bufsz - cnt, val, IB_PC_XMT_INACT_DISC_F,
+                    IB_PC_XMT_DISC_LAST_F);
+}
+
+void mad_dump_perfcounters_rcv_err(char *buf, int bufsz, void *val, int valsz)
+{
+       int cnt;
+
+       cnt = _dump_fields(buf, bufsz, val, IB_PC_EXT_PORT_SELECT_F,
+                          IB_PC_EXT_XMT_BYTES_F);
+       _dump_fields(buf + cnt, bufsz - cnt, val, IB_PC_RCV_LOCAL_PHY_ERR_F,
+                    IB_PC_RCV_ERR_LAST_F);
+}
+
+void mad_dump_portsamples_control(char *buf, int bufsz, void *val, int valsz)
+{
+       _dump_fields(buf, bufsz, val, IB_PSC_OPCODE_F, IB_PSC_LAST_F);
+}
+
 void xdump(FILE * file, char *msg, void *p, int size)
 {
 #define HEX(x)  ((x) < 10 ? '0' + (x) : 'a' + ((x) -10))
index 5f301167049c7dc0266798c374dc1bd831f23586..a5a510a4b93a321ec5afe5dfc7b7ec5457c64683 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2007 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
  * Copyright (c) 2009 HNR Consulting.  All rights reserved.
  * Copyright (c) 2009 Mellanox Technologies LTD.  All rights reserved.
  *
@@ -162,6 +162,7 @@ static const ib_field_t ib_mad_f[] = {
        {BITSOFFS(384, 16), "QkeyViolations", mad_dump_uint},
        {BITSOFFS(400, 8), "GuidCap", mad_dump_uint},
        {BITSOFFS(408, 1), "ClientReregister", mad_dump_uint},
+       {BITSOFFS(409, 1), "McastPkeyTrapSuppressionEnabled", mad_dump_uint},
        {BITSOFFS(411, 5), "SubnetTimeout", mad_dump_uint},
        {BITSOFFS(419, 5), "RespTimeVal", mad_dump_uint},
        {BITSOFFS(424, 4), "LocalPhysErr", mad_dump_uint},
@@ -406,6 +407,9 @@ static const ib_field_t ib_mad_f[] = {
        {BITSOFFS(520, 24), "TrapQP", mad_dump_hex},
        {544, 32, "TrapQKey", mad_dump_hex},
 
+       /*
+        * PortXmitDataSL fields
+        */
        {32, 32, "XmtDataSL0", mad_dump_uint},
        {64, 32, "XmtDataSL1", mad_dump_uint},
        {96, 32, "XmtDataSL2", mad_dump_uint},
@@ -424,6 +428,9 @@ static const ib_field_t ib_mad_f[] = {
        {512, 32, "XmtDataSL15", mad_dump_uint},
        {0, 0},                 /* IB_PC_XMT_DATA_SL_LAST_F */
 
+       /*
+        * PortRcvDataSL fields
+        */
        {32, 32, "RcvDataSL0", mad_dump_uint},
        {64, 32, "RcvDataSL1", mad_dump_uint},
        {96, 32, "RcvDataSL2", mad_dump_uint},
@@ -442,6 +449,61 @@ static const ib_field_t ib_mad_f[] = {
        {512, 32, "RcvDataSL15", mad_dump_uint},
        {0, 0},                 /* IB_PC_RCV_DATA_SL_LAST_F */
 
+       /*
+        * PortXmitDiscardDetails fields
+        */
+       {32, 16, "PortInactiveDiscards", mad_dump_uint},
+       {48, 16, "PortNeighborMTUDiscards", mad_dump_uint},
+       {64, 16, "PortSwLifetimeLimitDiscards", mad_dump_uint},
+       {80, 16, "PortSwHOQLifetimeLimitDiscards", mad_dump_uint},
+       {0, 0},                 /* IB_PC_XMT_DISC_LAST_F */
+
+       /*
+        * PortRcvErrorDetails fields
+        */
+       {32, 16, "PortLocalPhysicalErrors", mad_dump_uint},
+       {48, 16, "PortMalformedPktErrors", mad_dump_uint},
+       {64, 16, "PortBufferOverrunErrors", mad_dump_uint},
+       {80, 16, "PortDLIDMappingErrors", mad_dump_uint},
+       {96, 16, "PortVLMappingErrors", mad_dump_uint},
+       {112, 16, "PortLoopingErrors", mad_dump_uint},
+       {0, 0},                 /* IB_PC_RCV_ERR_LAST_F */
+
+       /*
+        * PortSamplesControl fields
+        */
+       {BITSOFFS(0, 8), "OpCode", mad_dump_hex},
+       {BITSOFFS(8, 8), "PortSelect", mad_dump_uint},
+       {BITSOFFS(16, 8), "Tick", mad_dump_hex},
+       {BITSOFFS(29, 3), "CounterWidth", mad_dump_uint},
+       {BITSOFFS(34, 3), "CounterMask0", mad_dump_hex},
+       {BITSOFFS(37, 27), "CounterMasks1to9", mad_dump_hex},
+       {BITSOFFS(65, 15), "CounterMasks10to14", mad_dump_hex},
+       {BITSOFFS(80, 8), "SampleMechanisms", mad_dump_uint},
+       {BITSOFFS(94, 2), "SampleStatus", mad_dump_uint},
+       {96, 64, "OptionMask", mad_dump_hex},
+       {160, 64, "VendorMask", mad_dump_hex},
+       {224, 32, "SampleStart", mad_dump_uint},
+       {256, 32, "SampleInterval", mad_dump_uint},
+       {288, 16, "Tag", mad_dump_hex},
+       {304, 16, "CounterSelect0", mad_dump_hex},
+       {320, 16, "CounterSelect1", mad_dump_hex},
+       {336, 16, "CounterSelect2", mad_dump_hex},
+       {352, 16, "CounterSelect3", mad_dump_hex},
+       {368, 16, "CounterSelect4", mad_dump_hex},
+       {384, 16, "CounterSelect5", mad_dump_hex},
+       {400, 16, "CounterSelect6", mad_dump_hex},
+       {416, 16, "CounterSelect7", mad_dump_hex},
+       {432, 16, "CounterSelect8", mad_dump_hex},
+       {448, 16, "CounterSelect9", mad_dump_hex},
+       {464, 16, "CounterSelect10", mad_dump_hex},
+       {480, 16, "CounterSelect11", mad_dump_hex},
+       {496, 16, "CounterSelect12", mad_dump_hex},
+       {512, 16, "CounterSelect13", mad_dump_hex},
+       {528, 16, "CounterSelect14", mad_dump_hex},
+       {576, 64, "SamplesOnlyOptionMask", mad_dump_hex},
+       {0, 0},                 /* IB_PSC_LAST_F */
+
        {0, 0}                  /* IB_FIELD_LAST_ */
 
 };
index 4701866f4bcb097874f718fc26621fcd245227ff..3cb2b25a503510805c4fd66810aec5984b581d61 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2007 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2004-2009 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
index b9a890cd785bf8658cc428d992e60f20abe4e6d8..5778e3e9e72757b902643a5d6f3f69fd097f61b6 100644 (file)
@@ -20,13 +20,17 @@ IBMAD_1.3 {
                mad_dump_nodedesc;
                mad_dump_nodeinfo;
                mad_dump_opervls;
+               mad_dump_fields;
                mad_dump_perfcounters;
                mad_dump_perfcounters_ext;
                mad_dump_perfcounters_xmt_sl;
                mad_dump_perfcounters_rcv_sl;
+               mad_dump_perfcounters_xmt_disc;
+               mad_dump_perfcounters_rcv_err;
                mad_dump_physportstate;
                mad_dump_portcapmask;
                mad_dump_portinfo;
+               mad_dump_portsamples_control;
                mad_dump_portstates;
                mad_dump_portstate;
                mad_dump_rhex;
index cfcff05aac705fc129130e406c389b83e0d69c00..acd0e85bd7406ecb22db7874e4aeeb147eb501d5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2007 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
  * Copyright (c) 2009 HNR Consulting.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
index 475adfcb6d8757e0fce247a758f2d357a0960742..3c32d10070f1b7e577c97df42c7c19cf5fbe82f8 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2006 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2004-2009 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
index 6f8fea2f2de1d98f904721a00fa57fc5c8ffce8a..ceb685ec086885f23637ef486d62d1d86cad599e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2008 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2004-2009 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
index adc6c87a69dd9884e0673228de1dead0dd7fcbfa..0ff8006ad34dc0bfc5cdb479e9137e4a0da48306 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004,2005 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2004-2009 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
index 3e07e8a5fd77c0f09b3926ca0d2ed1286256f021..f866bf4c3e1e389c664ca3a06b6f412ac1cea74e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2006 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
  * Copyright (c) 2009 HNR Consulting.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -98,7 +98,7 @@ int ib_resolve_guid_via(ib_portid_t * portid, uint64_t * guid,
        ib_portid_t sm_portid;
        uint8_t buf[IB_SA_DATA_SIZE] = { 0 };
        ib_portid_t self = { 0 };
-       uint64_t selfguid;
+       uint64_t selfguid, prefix;
        ibmad_gid_t selfgid;
        uint8_t nodeinfo[64];
 
@@ -114,7 +114,8 @@ int ib_resolve_guid_via(ib_portid_t * portid, uint64_t * guid,
        mad_set_field64(selfgid, 0, IB_GID_PREFIX_F, IB_DEFAULT_SUBN_PREFIX);
        mad_set_field64(selfgid, 0, IB_GID_GUID_F, selfguid);
 
-       if (*(uint64_t *) & portid->gid == 0)
+       memcpy(&prefix, portid->gid, sizeof(prefix));
+       if (!prefix)
                mad_set_field64(portid->gid, 0, IB_GID_PREFIX_F,
                                IB_DEFAULT_SUBN_PREFIX);
        if (guid)
index 1ea9a52942d44436b5ca817bd75e0aa9084f5d9d..c5246fed1ad66d7c2ac6e038c2830c4652d088fc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2006 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
  * Copyright (c) 2009 HNR Consulting.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
index 5f3403954c1ab11f37b1a0667b5e211a45f30b13..a9a93cccbdcce388038fb0ea501c2b12fd6e532a 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2007 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2004-2009 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
index 15297ad611f2f320bebb0706adc457bb9e589727..df61f259be846a6343b7e02e277d0eb7acb02f70 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004,2005 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2004-2009 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
index 5f55ec5842373d046c89e2e36b1326a1d4dee70e..3ff58ce412fa3cf09f62a87974411a57b0de7045 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2007 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2004-2009 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
index 6736f32f6791867b0a79d5e416a5fc20b635af02..11efd76ec635adb8099603d5fc56310822ee66c0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004,2005 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2004-2009 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
index c55ce0042560e956ce6ae8857f43ee5d5fbc58f4..49ff74346ce3412e496a61948415853fe922edb2 100644 (file)
@@ -1,4 +1,5 @@
 /*
+ * Copyright (c) 2009 Voltaire, Inc. All rights reserved.
  * Copyright (c) 2008 Lawrence Livermore National Lab.  All rights reserved.
  *
  * This software is available to you under a choice of one of two
@@ -48,9 +49,8 @@ typedef struct ibnd_node {
        struct ibnd_node *next; /* all node list in fabric */
 
        ib_portid_t path_portid;        /* path from "from_node" */
-       int dist;               /* num of hops from "from_node" */
-       int smalid;
-       int smalmc;
+       uint16_t smalid;
+       uint8_t smalmc;
 
        /* quick cache of switchinfo below */
        int smaenhsp0;
@@ -66,9 +66,14 @@ typedef struct ibnd_node {
 
        char nodedesc[IB_SMP_DATA_SIZE];
 
-       struct ibnd_port **ports;       /* in order array of port pointers
-                                          the size of this array is info.numports + 1
-                                          items MAY BE NULL!  (ie 0 == switches only) */
+       struct ibnd_port **ports;       /* array of ports, indexed by port number
+                                          ports[1] == port 1,
+                                          ports[2] == port 2,
+                                          etc...
+                                          Any port in the array MAY BE NULL!
+                                          Most notable is non-switches have no
+                                          port 0 therefore node.ports[0] == NULL
+                                          for those nodes */
 
        /* chassis info */
        struct ibnd_node *next_chassis_node;    /* next node in ibnd_chassis_t->nodes */
@@ -81,7 +86,6 @@ typedef struct ibnd_node {
        /* internal use only */
        unsigned char ch_found;
        struct ibnd_node *htnext;       /* hash table list */
-       struct ibnd_node *dnext;        /* nodesdist next */
        struct ibnd_node *type_next;    /* next based on type */
 } ibnd_node_t;
 
@@ -117,14 +121,23 @@ typedef struct ibnd_chassis {
        ibnd_node_t *nodes;
 
        /* specific to voltaire type nodes */
-#define SPINES_MAX_NUM 12
+#define SPINES_MAX_NUM 18
 #define LINES_MAX_NUM 36
        ibnd_node_t *spinenode[SPINES_MAX_NUM + 1];
        ibnd_node_t *linenode[LINES_MAX_NUM + 1];
 } ibnd_chassis_t;
 
 #define HTSZ 137
-#define MAXHOPS                63
+
+typedef struct ibnd_config {
+       unsigned max_smps;
+       unsigned show_progress;
+       unsigned max_hops;
+       unsigned debug;
+       unsigned timeout_ms;
+       unsigned retries;
+       uint8_t pad[56];
+} ibnd_config_t;
 
 /** =========================================================================
  * Fabric
@@ -140,66 +153,65 @@ typedef struct ibnd_fabric {
        ibnd_node_t *nodes;
        /* NULL terminated list of all chassis found in the fabric */
        ibnd_chassis_t *chassis;
-       int maxhops_discovered;
+       unsigned maxhops_discovered;
+       unsigned total_mads_used;
 
        /* internal use only */
        ibnd_node_t *nodestbl[HTSZ];
        ibnd_port_t *portstbl[HTSZ];
-       ibnd_node_t *nodesdist[MAXHOPS + 1];
-       ibnd_chassis_t *first_chassis;
-       ibnd_chassis_t *current_chassis;
-       ibnd_chassis_t *last_chassis;
        ibnd_node_t *switches;
        ibnd_node_t *ch_adapters;
        ibnd_node_t *routers;
-       ib_portid_t selfportid;
 } ibnd_fabric_t;
 
 /** =========================================================================
  * Initialization (fabric operations)
  */
-MAD_EXPORT void ibnd_debug(int i);
-MAD_EXPORT void ibnd_show_progress(int i);
 
-MAD_EXPORT ibnd_fabric_t *ibnd_discover_fabric(struct ibmad_port *ibmad_port,
-                                              ib_portid_t * from, int hops);
+IBND_EXPORT ibnd_fabric_t *ibnd_discover_fabric(char * ca_name,
+                                              int ca_port,
+                                              ib_portid_t * from,
+                                              struct ibnd_config *config);
        /**
-        * open: (required) ibmad_port object from libibmad
+        * ca_name: (optional) name of the CA to use
+        * ca_port: (optional) CA port to use
         * from: (optional) specify the node to start scanning from.
-        *       If NULL start from the node we are running on.
-        * hops: (optional) Specify how much of the fabric to traverse.
-        *       negative value == scan entire fabric
+        *       If NULL start from the CA/CA port specified
+        * config: (optional) additional config options for the scan
         */
-MAD_EXPORT void ibnd_destroy_fabric(ibnd_fabric_t * fabric);
+IBND_EXPORT void ibnd_destroy_fabric(ibnd_fabric_t * fabric);
+
+IBND_EXPORT ibnd_fabric_t *ibnd_load_fabric(const char *file,
+                                          unsigned int flags);
+
+IBND_EXPORT int ibnd_cache_fabric(ibnd_fabric_t * fabric, const char *file,
+                                unsigned int flags);
 
 /** =========================================================================
  * Node operations
  */
-MAD_EXPORT ibnd_node_t *ibnd_find_node_guid(ibnd_fabric_t * fabric,
+IBND_EXPORT ibnd_node_t *ibnd_find_node_guid(ibnd_fabric_t * fabric,
                                            uint64_t guid);
-MAD_EXPORT ibnd_node_t *ibnd_find_node_dr(ibnd_fabric_t * fabric, char *dr_str);
-MAD_EXPORT ibnd_node_t *ibnd_update_node(struct ibmad_port *ibmad_port,
-                                        ibnd_fabric_t * fabric,
-                                        ibnd_node_t * node);
+IBND_EXPORT ibnd_node_t *ibnd_find_node_dr(ibnd_fabric_t * fabric, char *dr_str);
 
 typedef void (*ibnd_iter_node_func_t) (ibnd_node_t * node, void *user_data);
-MAD_EXPORT void ibnd_iter_nodes(ibnd_fabric_t * fabric,
+IBND_EXPORT void ibnd_iter_nodes(ibnd_fabric_t * fabric,
                                ibnd_iter_node_func_t func, void *user_data);
-MAD_EXPORT void ibnd_iter_nodes_type(ibnd_fabric_t * fabric,
+IBND_EXPORT void ibnd_iter_nodes_type(ibnd_fabric_t * fabric,
                                     ibnd_iter_node_func_t func,
                                     int node_type, void *user_data);
 
 /** =========================================================================
  * Chassis queries
  */
-MAD_EXPORT uint64_t ibnd_get_chassis_guid(ibnd_fabric_t * fabric,
+IBND_EXPORT uint64_t ibnd_get_chassis_guid(ibnd_fabric_t * fabric,
                                          unsigned char chassisnum);
-MAD_EXPORT char *ibnd_get_chassis_type(ibnd_node_t * node);
-MAD_EXPORT char *ibnd_get_chassis_slot_str(ibnd_node_t * node,
+IBND_EXPORT char *ibnd_get_chassis_type(ibnd_node_t * node);
+IBND_EXPORT char *ibnd_get_chassis_slot_str(ibnd_node_t * node,
                                           char *str, size_t size);
 
-MAD_EXPORT int ibnd_is_xsigo_guid(uint64_t guid);
-MAD_EXPORT int ibnd_is_xsigo_tca(uint64_t guid);
-MAD_EXPORT int ibnd_is_xsigo_hca(uint64_t guid);
+IBND_EXPORT int ibnd_is_xsigo_guid(uint64_t guid);
+IBND_EXPORT int ibnd_is_xsigo_tca(uint64_t guid);
+IBND_EXPORT int ibnd_is_xsigo_hca(uint64_t guid);
 
 #endif                         /* _IBNETDISC_H_ */
diff --git a/trunk/ulp/libibnetdisc/include/windows/config.h b/trunk/ulp/libibnetdisc/include/windows/config.h
new file mode 100644 (file)
index 0000000..e473993
--- /dev/null
@@ -0,0 +1,53 @@
+/*\r
+ * Copyright (c) 2009 Intel Corp, Inc.  All rights reserved.\r
+ *\r
+ * This software is available to you under a choice of one of two\r
+ * licenses.  You may choose to be licensed under the terms of the GNU\r
+ * General Public License (GPL) Version 2, available from the file\r
+ * COPYING in the main directory of this source tree, or the\r
+ * OpenIB.org BSD license below:\r
+ *\r
+ *     Redistribution and use in source and binary forms, with or\r
+ *     without modification, are permitted provided that the following\r
+ *     conditions are met:\r
+ *\r
+ *      - Redistributions of source code must retain the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer.\r
+ *\r
+ *      - Redistributions in binary form must reproduce the above\r
+ *        copyright notice, this list of conditions and the following\r
+ *        disclaimer in the documentation and/or other materials\r
+ *        provided with the distribution.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\r
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\r
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r
+ * SOFTWARE.\r
+ *\r
+ */\r
+\r
+#ifndef _CONFIG_H_\r
+#define _CONFIG_H_\r
+\r
+#include <_errno.h>\r
+#include <io.h>\r
+#include <sys/types.h>\r
+#include <sys/stat.h>\r
+\r
+#define ssize_t SSIZE_T\r
+#define read _read\r
+#define write _write\r
+#define stat _stat\r
+#define open _open\r
+#define close _close\r
+#define lseek _lseek\r
+#define unlink _unlink\r
+\r
+#define IBND_EXPORT    __declspec(dllexport)\r
+\r
+#endif /* _CONFIG_H_ */\r
index 92ce29faec5b7282d08efcec07d42bce02e6a6aa..f67686d67e957edfb88049bcf8d326fa1a6a68f7 100644 (file)
@@ -12,13 +12,10 @@ DLLDEF = $(OBJ_PATH)\$O\ibnetdisc_exports.def
 DLLENTRY = DllMain\r
 USE_MSVCRT = 1\r
 \r
-SOURCES = \\r
-       ibnetdisc_main.cpp \\r
-       ibnetdisc.c \\r
-       chassis.c\r
+SOURCES = ibnetdisc_main.cpp ibnetdisc.c chassis.c query_smp.c ibnetdisc_cache.c\r
        \r
 INCLUDES =     ..\include\infiniband;\\r
-                       ..\include;\\r
+                       ..\include;..\include\windows;\\r
                        ..\..\libibmad\include;\\r
                        ..\..\..\tools\infiniband-diags\include;\\r
                        ..\..\libibverbs\include;\\r
@@ -28,6 +25,7 @@ INCLUDES =    ..\include\infiniband;\
                        ..\..\..\inc\user\linux;\r
 \r
 USER_C_FLAGS = $(USER_C_FLAGS)\r
+C_DEFINES = $(C_DEFINES) /DHAVE_CONFIG_H\r
 \r
 TARGETLIBS = \\r
        $(SDK_LIB_PATH)\kernel32.lib    \\r
@@ -38,8 +36,10 @@ TARGETLIBS = \
        $(SDK_LIB_PATH)\ole32.lib               \\r
 !if $(FREEBUILD)\r
        $(TARGETPATH)\*\libibumad.lib   \\r
-       $(TARGETPATH)\*\libibmad.lib   \r
+       $(TARGETPATH)\*\libibmad.lib    \\r
+       $(TARGETPATH)\*\complib.lib\r
 !else\r
        $(TARGETPATH)\*\libibumadd.lib  \\r
-       $(TARGETPATH)\*\libibmadd.lib  \r
+       $(TARGETPATH)\*\libibmadd.lib   \\r
+       $(TARGETPATH)\*\complibd.lib\r
 !endif\r
index 4886cfc3e69674d5ad585843f1f39a188b9a0392..25d7473a1d47149531340e63fb2b87240042d459 100644 (file)
@@ -1,7 +1,8 @@
 /*
- * Copyright (c) 2004-2007 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
  * Copyright (c) 2007 Xsigo Systems Inc.  All rights reserved.
  * Copyright (c) 2008 Lawrence Livermore National Lab.  All rights reserved.
+ * Copyright (c) 2010 HNR Consulting.  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
@@ -38,7 +39,7 @@
 /*========================================================*/
 
 #if HAVE_CONFIG_H
-#  include <config.h>
+#include <config.h>
 #endif                         /* HAVE_CONFIG_H */
 
 #include <stdlib.h>
 #include "internal.h"
 #include "chassis.h"
 
-static char *ChassisTypeStr[5] =
-    { "", "ISR9288", "ISR9096", "ISR2012", "ISR2004" };
+static char *ChassisTypeStr[6] =
+{ "", "ISR9288", "ISR9096", "ISR2012", "ISR2004", "ISR4700" };
 static char *ChassisSlotTypeStr[4] = { "", "Line", "Spine", "SRBD" };
 
+typedef struct chassis_scan {
+       ibnd_chassis_t *first_chassis;
+       ibnd_chassis_t *current_chassis;
+       ibnd_chassis_t *last_chassis;
+} chassis_scan_t;
+
 char *ibnd_get_chassis_type(ibnd_node_t * node)
 {
        if (!node) {
                IBND_DEBUG("node parameter NULL\n");
-               return (NULL);
+               return NULL;
        }
 
        /* Currently, only if Voltaire chassis */
        if (mad_get_field(node->info, 0, IB_NODE_VENDORID_F) != VTR_VENDOR_ID)
-               return (NULL);
+               return NULL;
        if (!node->chassis)
-               return (NULL);
-       if (node->ch_type == UNRESOLVED_CT || node->ch_type > ISR2004_CT)
-               return (NULL);
+               return NULL;
+       if (node->ch_type == UNRESOLVED_CT || node->ch_type > ISR4700_CT)
+               return NULL;
        return ChassisTypeStr[node->ch_type];
 }
 
@@ -74,21 +81,21 @@ char *ibnd_get_chassis_slot_str(ibnd_node_t * node, char *str, size_t size)
 {
        if (!node) {
                IBND_DEBUG("node parameter NULL\n");
-               return (NULL);
+               return NULL;
        }
 
        /* Currently, only if Voltaire chassis */
        if (mad_get_field(node->info, 0, IB_NODE_VENDORID_F) != VTR_VENDOR_ID)
-               return (NULL);
+               return NULL;
        if (!node->chassis)
-               return (NULL);
+               return NULL;
        if (node->ch_slot == UNRESOLVED_CS || node->ch_slot > SRBD_CS)
-               return (NULL);
+               return NULL;
        if (!str)
-               return (NULL);
+               return NULL;
        snprintf(str, size, "%s %d Chip %d", ChassisSlotTypeStr[node->ch_slot],
                 node->ch_slotnum, node->ch_anafanum);
-       return (str);
+       return str;
 }
 
 static ibnd_chassis_t *find_chassisnum(ibnd_fabric_t * fabric,
@@ -96,10 +103,9 @@ static ibnd_chassis_t *find_chassisnum(ibnd_fabric_t * fabric,
 {
        ibnd_chassis_t *current;
 
-       for (current = fabric->first_chassis; current; current = current->next) {
+       for (current = fabric->chassis; current; current = current->next)
                if (current->chassisnum == chassisnum)
                        return current;
-       }
 
        return NULL;
 }
@@ -176,7 +182,7 @@ static uint64_t xsigo_chassisguid(ibnd_node_t * node)
                        return sysimgguid;
        } else {
                if (!node->ports || !node->ports[1])
-                       return (0);
+                       return 0;
 
                /* Is there a peer port ? */
                if (!node->ports[1]->remoteport)
@@ -214,10 +220,9 @@ static ibnd_chassis_t *find_chassisguid(ibnd_fabric_t * fabric,
        uint64_t chguid;
 
        chguid = get_chassisguid(node);
-       for (current = fabric->first_chassis; current; current = current->next) {
+       for (current = fabric->chassis; current; current = current->next)
                if (current->chassisguid == chguid)
                        return current;
-       }
 
        return NULL;
 }
@@ -269,10 +274,23 @@ static int is_spine_2012(ibnd_node_t * n)
        return (devid == VTR_DEVID_SFB2012);
 }
 
+static int is_spine_4700(ibnd_node_t * n)
+{
+       uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F);
+       return (devid == VTR_DEVID_SFB4700);
+}
+
+static int is_spine_4700x2(ibnd_node_t * n)
+{
+       uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F);
+       return (devid == VTR_DEVID_SFB4700X2);
+}
+
 static int is_spine(ibnd_node_t * n)
 {
        return (is_spine_9096(n) || is_spine_9288(n) ||
-               is_spine_2004(n) || is_spine_2012(n));
+               is_spine_2004(n) || is_spine_2012(n) ||
+               is_spine_4700(n) || is_spine_4700x2(n));
 }
 
 static int is_line_24(ibnd_node_t * n)
@@ -294,9 +312,16 @@ static int is_line_2024(ibnd_node_t * n)
        return (devid == VTR_DEVID_SLB2024);
 }
 
+static int is_line_4700(ibnd_node_t * n)
+{
+       uint32_t devid = mad_get_field(n->info, 0, IB_NODE_DEVID_F);
+       return (devid == VTR_DEVID_SLB4018);
+}
+
 static int is_line(ibnd_node_t * n)
 {
-       return (is_line_24(n) || is_line_8(n) || is_line_2024(n));
+       return (is_line_24(n) || is_line_8(n) ||
+               is_line_2024(n) || is_line_4700(n));
 }
 
 int is_chassis_switch(ibnd_node_t * n)
@@ -305,76 +330,136 @@ int is_chassis_switch(ibnd_node_t * n)
 }
 
 /* these structs help find Line (Anafa) slot number while using spine portnum */
-char line_slot_2_sfb4[25] = {
-       0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4,
-       4
+char line_slot_2_sfb4[37] = {
+       0,
+       1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3,
+       4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 };
-char anafa_line_slot_2_sfb4[25] = {
-       0, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2,
-       2
+char anafa_line_slot_2_sfb4[37] = {
+       0,
+       1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2, 1, 1, 1, 2, 2, 2,
+       1, 1, 1, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 };
-char line_slot_2_sfb12[25] = {
-       0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
-       12, 12
+
+char line_slot_2_sfb12[37] = {
+       0,
+       1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,
+       10, 10, 11, 11, 12, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 };
-char anafa_line_slot_2_sfb12[25] = {
-       0, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1,
-       2
+char anafa_line_slot_2_sfb12[37] = {
+       0,
+       1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2,
+       1, 2, 1, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/* LB slot = table[spine port] */
+char line_slot_2_sfb18[37] = {
+       0,
+       1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,
+       10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18};
+/* LB asic num = table[spine port] */
+char anafa_line_slot_2_sfb18[37] = {
+       0,
+       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
+};
+
+/* LB slot = table[spine port] */
+char line_slot_2_sfb18x2[37] = {
+       0,
+       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
+       0, 0, 0, 0, 0, 0, 0, 0, 0,  0,  0,  0,  0,  0,  0,  0,  0,  0};
+/* LB asic num = table[spine port] */
+char anafa_line_slot_2_sfb18x2[37] = {
+       0,
+       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 };
 
 /* IPR FCR modules connectivity while using sFB4 port as reference */
-char ipr_slot_2_sfb4_port[25] = {
-       0, 3, 2, 1, 3, 2, 1, 3, 2, 1, 3, 2, 1, 3, 2, 1, 3, 2, 1, 3, 2, 1, 3, 2,
-       1
+char ipr_slot_2_sfb4_port[37] = {
+       0,
+       3, 2, 1, 3, 2, 1, 3, 2, 1, 3, 2, 1, 3, 2, 1, 3, 2, 1,
+       3, 2, 1, 3, 2, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 };
 
 /* these structs help find Spine (Anafa) slot number while using spine portnum */
-char spine12_slot_2_slb[25] = {
-       0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-       0
+char spine12_slot_2_slb[37] = {
+       0,
+       1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+char anafa_spine12_slot_2_slb[37] = {
+       0,
+       1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+char spine4_slot_2_slb[37] = {
+       0,
+       1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+char anafa_spine4_slot_2_slb[37] = {
+       0,
+       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 };
-char anafa_spine12_slot_2_slb[25] = {
-       0, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-       0
+
+/* FB slot = table[line port] */
+char spine18_slot_2_slb[37] = {
+       0,
+       1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 };
-char spine4_slot_2_slb[25] = {
-       0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-       0
+/* FB asic = table[line port] */
+char anafa_spine18_slot_2_slb[37] = {
+       0,
+       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 };
-char anafa_spine4_slot_2_slb[25] = {
-       0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-       0
+char anafa_spine18x2_slot_2_slb[37] = {
+       0,
+       2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
 };
 
+
 /*     reference                     { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 }; */
 
-static int get_sfb_slot(ibnd_node_t * node, ibnd_port_t * lineport)
+static int get_sfb_slot(ibnd_node_t * n, ibnd_port_t * lineport)
 {
-       ibnd_node_t *n = (ibnd_node_t *) node;
-
        n->ch_slot = SPINE_CS;
-       if (is_spine_9096(node)) {
+       if (is_spine_9096(n)) {
                n->ch_type = ISR9096_CT;
                n->ch_slotnum = spine4_slot_2_slb[lineport->portnum];
                n->ch_anafanum = anafa_spine4_slot_2_slb[lineport->portnum];
-       } else if (is_spine_9288(node)) {
+       } else if (is_spine_9288(n)) {
                n->ch_type = ISR9288_CT;
                n->ch_slotnum = spine12_slot_2_slb[lineport->portnum];
                n->ch_anafanum = anafa_spine12_slot_2_slb[lineport->portnum];
-       } else if (is_spine_2012(node)) {
+       } else if (is_spine_2012(n)) {
                n->ch_type = ISR2012_CT;
                n->ch_slotnum = spine12_slot_2_slb[lineport->portnum];
                n->ch_anafanum = anafa_spine12_slot_2_slb[lineport->portnum];
-       } else if (is_spine_2004(node)) {
+       } else if (is_spine_2004(n)) {
                n->ch_type = ISR2004_CT;
                n->ch_slotnum = spine4_slot_2_slb[lineport->portnum];
                n->ch_anafanum = anafa_spine4_slot_2_slb[lineport->portnum];
+       } else if (is_spine_4700(n)) {
+               n->ch_type = ISR4700_CT;
+               n->ch_slotnum = spine18_slot_2_slb[lineport->portnum];
+               n->ch_anafanum = anafa_spine18_slot_2_slb[lineport->portnum];
+       } else if (is_spine_4700x2(n)) {
+               n->ch_type = ISR4700_CT;
+               n->ch_slotnum = spine18_slot_2_slb[lineport->portnum];
+               n->ch_anafanum = anafa_spine18x2_slot_2_slb[lineport->portnum];
        } else {
-               IBND_ERROR("Unexpected node found: guid 0x%016" PRIx64,
-                          node->guid);
-               return (-1);
+               IBND_ERROR("Unexpected node found: guid 0x%016" PRIx64 "\n",
+                          n->guid);
+               return -1;
        }
-       return (0);
+       return 0;
 }
 
 static int get_router_slot(ibnd_node_t * n, ibnd_port_t * spineport)
@@ -411,11 +496,11 @@ static int get_router_slot(ibnd_node_t * n, ibnd_port_t * spineport)
                n->ch_slotnum = line_slot_2_sfb4[spineport->portnum];
                n->ch_anafanum = ipr_slot_2_sfb4_port[spineport->portnum];
        } else {
-               IBND_ERROR("Unexpected node found: guid 0x%016" PRIx64,
+               IBND_ERROR("Unexpected node found: guid 0x%016" PRIx64 "\n",
                           spineport->node->guid);
-               return (-1);
+               return -1;
        }
-       return (0);
+       return 0;
 }
 
 static int get_slb_slot(ibnd_node_t * n, ibnd_port_t * spineport)
@@ -437,12 +522,20 @@ static int get_slb_slot(ibnd_node_t * n, ibnd_port_t * spineport)
                n->ch_type = ISR2004_CT;
                n->ch_slotnum = line_slot_2_sfb4[spineport->portnum];
                n->ch_anafanum = anafa_line_slot_2_sfb4[spineport->portnum];
+       } else if (is_spine_4700(spineport->node)) {
+               n->ch_type = ISR4700_CT;
+               n->ch_slotnum = line_slot_2_sfb18[spineport->portnum];
+               n->ch_anafanum = anafa_line_slot_2_sfb18[spineport->portnum];
+       } else if (is_spine_4700x2(spineport->node)) {
+               n->ch_type = ISR4700_CT;
+               n->ch_slotnum = line_slot_2_sfb18x2[spineport->portnum];
+               n->ch_anafanum = anafa_line_slot_2_sfb18x2[spineport->portnum];
        } else {
-               IBND_ERROR("Unexpected node found: guid 0x%016" PRIx64,
+               IBND_ERROR("Unexpected node found: guid 0x%016" PRIx64 "\n",
                           spineport->node->guid);
-               return (-1);
+               return -1;
        }
-       return (0);
+       return 0;
 }
 
 /* forward declare this */
@@ -459,24 +552,34 @@ static int fill_voltaire_chassis_record(ibnd_node_t * node)
        ibnd_node_t *remnode = 0;
 
        if (node->ch_found)     /* somehow this node has already been passed */
-               return (0);
+               return 0;
        node->ch_found = 1;
 
        /* node is router only in case of using unique lid */
        /* (which is lid of chassis router port) */
        /* in such case node->ports is actually a requested port... */
-       if (is_router(node)) {
+       if (is_router(node))
                /* find the remote node */
                for (p = 1; p <= node->numports; p++) {
                        port = node->ports[p];
                        if (port && is_spine(port->remoteport->node))
                                get_router_slot(node, port->remoteport);
                }
-       } else if (is_spine(node)) {
+       else if (is_spine(node)) {
+               int is_4700x2 = is_spine_4700x2(node);
+
                for (p = 1; p <= node->numports; p++) {
                        port = node->ports[p];
                        if (!port || !port->remoteport)
                                continue;
+
+                       /*
+                        * Skip ISR4700 double density fabric boards ports 19-36
+                        * as they are chassis external ports
+                        */
+                       if (is_4700x2 && (port->portnum > 18))
+                               continue;
+
                        remnode = port->remoteport->node;
                        if (remnode->type != IB_NODE_SWITCH) {
                                if (!remnode->ch_found)
@@ -486,19 +589,26 @@ static int fill_voltaire_chassis_record(ibnd_node_t * node)
                        if (!node->ch_type)
                                /* we assume here that remoteport belongs to line */
                                if (get_sfb_slot(node, port->remoteport))
-                                       return (-1);
+                                       return -1;
 
                        /* we could break here, but need to find if more routers connected */
                }
 
        } else if (is_line(node)) {
+               int is_4700_line = is_line_4700(node);
+
                for (p = 1; p <= node->numports; p++) {
                        port = node->ports[p];
-                       if (!port || port->portnum > 12 || !port->remoteport)
+                       if (!port || !port->remoteport)
+                               continue;
+
+                       if ((is_4700_line && (port->portnum > 18)) ||
+                           (!is_4700_line && (port->portnum > 12)))
                                continue;
+
                        /* we assume here that remoteport belongs to spine */
                        if (get_slb_slot(node, port->remoteport))
-                               return (-1);
+                               return -1;
                        break;
                }
        }
@@ -511,16 +621,22 @@ static int fill_voltaire_chassis_record(ibnd_node_t * node)
                voltaire_portmap(port);
        }
 
-       return (0);
+       return 0;
 }
 
 static int get_line_index(ibnd_node_t * node)
 {
-       int retval = 3 * (node->ch_slotnum - 1) + node->ch_anafanum;
+       int retval;
+
+       if (is_line_4700(node))
+               retval = node->ch_slotnum;
+       else
+               retval = 3 * (node->ch_slotnum - 1) + node->ch_anafanum;
 
        if (retval > LINES_MAX_NUM || retval < 1) {
+               printf("%s: retval = %d\n", __FUNCTION__, retval);
                IBND_ERROR("Internal error\n");
-               return (-1);
+               return -1;
        }
        return retval;
 }
@@ -531,12 +647,14 @@ static int get_spine_index(ibnd_node_t * node)
 
        if (is_spine_9288(node) || is_spine_2012(node))
                retval = 3 * (node->ch_slotnum - 1) + node->ch_anafanum;
+       else if (is_spine_4700(node) || is_spine_4700x2(node))
+               retval = 2 * (node->ch_slotnum - 1) + node->ch_anafanum;
        else
                retval = node->ch_slotnum;
 
        if (retval > SPINES_MAX_NUM || retval < 1) {
                IBND_ERROR("Internal error\n");
-               return (-1);
+               return -1;
        }
        return retval;
 }
@@ -546,14 +664,14 @@ static int insert_line_router(ibnd_node_t * node, ibnd_chassis_t * chassis)
        int i = get_line_index(node);
 
        if (i < 0)
-               return (i);
+               return i;
 
        if (chassis->linenode[i])
-               return (0);     /* already filled slot */
+               return 0;       /* already filled slot */
 
        chassis->linenode[i] = node;
        node->chassis = chassis;
-       return (0);
+       return 0;
 }
 
 static int insert_spine(ibnd_node_t * node, ibnd_chassis_t * chassis)
@@ -561,14 +679,14 @@ static int insert_spine(ibnd_node_t * node, ibnd_chassis_t * chassis)
        int i = get_spine_index(node);
 
        if (i < 0)
-               return (i);
+               return i;
 
        if (chassis->spinenode[i])
-               return (0);     /* already filled slot */
+               return 0;       /* already filled slot */
 
        chassis->spinenode[i] = node;
        node->chassis = chassis;
-       return (0);
+       return 0;
 }
 
 static int pass_on_lines_catch_spines(ibnd_chassis_t * chassis)
@@ -578,14 +696,23 @@ static int pass_on_lines_catch_spines(ibnd_chassis_t * chassis)
        int i, p;
 
        for (i = 1; i <= LINES_MAX_NUM; i++) {
+               int is_4700_line;
+
                node = chassis->linenode[i];
 
                if (!(node && is_line(node)))
                        continue;       /* empty slot or router */
 
+               is_4700_line = is_line_4700(node);
+
                for (p = 1; p <= node->numports; p++) {
+
                        port = node->ports[p];
-                       if (!port || port->portnum > 12 || !port->remoteport)
+                       if (!port || !port->remoteport)
+                               continue;
+
+                       if ((is_4700_line && (port->portnum > 18)) ||
+                           (!is_4700_line && (port->portnum > 12)))
                                continue;
 
                        remnode = port->remoteport->node;
@@ -593,10 +720,10 @@ static int pass_on_lines_catch_spines(ibnd_chassis_t * chassis)
                        if (!remnode->ch_found)
                                continue;       /* some error - spine not initialized ? FIXME */
                        if (insert_spine(remnode, chassis))
-                               return (-1);
+                               return -1;
                }
        }
-       return (0);
+       return 0;
 }
 
 static int pass_on_spines_catch_lines(ibnd_chassis_t * chassis)
@@ -606,22 +733,36 @@ static int pass_on_spines_catch_lines(ibnd_chassis_t * chassis)
        int i, p;
 
        for (i = 1; i <= SPINES_MAX_NUM; i++) {
+               int is_4700x2;
+
                node = chassis->spinenode[i];
                if (!node)
                        continue;       /* empty slot */
+
+               is_4700x2 = is_spine_4700x2(node);
+
                for (p = 1; p <= node->numports; p++) {
                        port = node->ports[p];
                        if (!port || !port->remoteport)
                                continue;
+
+                       /*
+                        * ISR4700 double density fabric board ports 19-36 are
+                        * chassis external ports, so skip them
+                        */
+                       if (is_4700x2 && (port->portnum > 18))
+                               continue;
+
                        remnode = port->remoteport->node;
 
                        if (!remnode->ch_found)
                                continue;       /* some error - line/router not initialized ? FIXME */
+
                        if (insert_line_router(remnode, chassis))
-                               return (-1);
+                               return -1;
                }
        }
-       return (0);
+       return 0;
 }
 
 /*
@@ -656,14 +797,23 @@ static int build_chassis(ibnd_node_t * node, ibnd_chassis_t * chassis)
        ibnd_port_t *port = 0;
 
        /* we get here with node = chassis_spine */
-       if (insert_spine((ibnd_node_t *) node, chassis))
-               return (-1);
+       if (insert_spine(node, chassis))
+               return -1;
 
        /* loop: pass on all ports of node */
        for (p = 1; p <= node->numports; p++) {
+
                port = node->ports[p];
                if (!port || !port->remoteport)
                        continue;
+
+               /*
+                * ISR4700 double density fabric board ports 19-36 are
+                * chassis external ports, so skip them
+                */
+               if (is_spine_4700x2(node) && (port->portnum > 18))
+                       continue;
+
                remnode = port->remoteport->node;
 
                if (!remnode->ch_found)
@@ -673,22 +823,22 @@ static int build_chassis(ibnd_node_t * node, ibnd_chassis_t * chassis)
        }
 
        if (pass_on_lines_catch_spines(chassis))
-               return (-1);
+               return -1;
        /* this pass needed for to catch routers, since routers connected only */
        /* to spines in slot 1 or 4 and we could miss them first time */
        if (pass_on_spines_catch_lines(chassis))
-               return (-1);
+               return -1;
 
        /* additional 2 passes needed for to overcome a problem of pure "in-chassis" */
        /* connectivity - extra pass to ensure that all related chips/modules */
        /* inserted into the chassis */
        if (pass_on_lines_catch_spines(chassis))
-               return (-1);
+               return -1;
        if (pass_on_spines_catch_lines(chassis))
-               return (-1);
+               return -1;
        pass_on_spines_interpolate_chguid(chassis);
 
-       return (0);
+       return 0;
 }
 
 /*========================================================*/
@@ -732,6 +882,21 @@ ext port | 1 2 3 4 5 6 7 8 9 10 11 12
 A2 int port| 13 14 15 16 17 18 19 20 21 22 23 24
 ---------------------------------------------------
 
+Module : sLB-4018
+
+int port | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
+ext port |  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18
+---------------------------------------------------
+
+Module : sFB-4700X2
+
+  12X port -> 3 x 4X ports:
+
+A1 int port | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
+   ext port |  7  7  7  8  8  8  9  9  9 10 10 10 11 11 11 12 12 12
+A2 int port | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
+   ext port |  1  1  1  2  2  2  3  3  3  4  4  4  5  5  5  6  6  6
+
 */
 
 int int2ext_map_slb24[2][25] = {
@@ -740,12 +905,14 @@ int int2ext_map_slb24[2][25] = {
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 12, 11, 10, 24, 23, 22, 7, 8, 9,
         19, 20, 21}
 };
+
 int int2ext_map_slb8[2][25] = {
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 6, 6, 6, 1, 1, 1, 5, 5,
         5},
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 4, 4, 8, 8, 8, 3, 3, 3, 7, 7,
         7}
 };
+
 int int2ext_map_slb2024[2][25] = {
        {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 13, 14, 15, 16, 17, 18, 19, 20,
         21, 22, 23, 24},
@@ -753,6 +920,21 @@ int int2ext_map_slb2024[2][25] = {
         11, 12}
 };
 
+int int2ext_map_slb4018[37] = {
+       0,
+       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18
+};
+
+int int2ext_map_sfb4700x2[2][37] = {
+       {0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 11, 12, 12, 12},
+       {0,
+        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+        1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6, 6}
+};
+
 /*     reference                       { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24 }; */
 
 /* map internal ports to external ports if appropriate */
@@ -761,12 +943,22 @@ static void voltaire_portmap(ibnd_port_t * port)
        int portnum = port->portnum;
        int chipnum = 0;
        ibnd_node_t *node = port->node;
+       int is_4700_line = is_line_4700(node);
+       int is_4700x2_spine = is_spine_4700x2(node);
 
-       if (!node->ch_found || !is_line(node) || (portnum < 13 || portnum > 24)) {
+       if (!node->ch_found || (!is_line(node) && !is_4700x2_spine)) {
                port->ext_portnum = 0;
                return;
        }
 
+       if (((is_4700_line || is_4700x2_spine) &&
+            (portnum < 19 || portnum > 36)) ||
+           ((!is_4700_line && !is_4700x2_spine) &&
+            (portnum < 13 || portnum > 24))) {
+                       port->ext_portnum = 0;
+               return;
+       }
+
        if (port->node->ch_anafanum < 1 || port->node->ch_anafanum > 2) {
                port->ext_portnum = 0;
                return;
@@ -778,25 +970,33 @@ static void voltaire_portmap(ibnd_port_t * port)
                port->ext_portnum = int2ext_map_slb24[chipnum][portnum];
        else if (is_line_2024(node))
                port->ext_portnum = int2ext_map_slb2024[chipnum][portnum];
+       /* sLB-4018: Only one asic per LB */
+       else if (is_4700_line)
+               port->ext_portnum = int2ext_map_slb4018[portnum];
+       /* sFB-4700X2 4X port */
+       else if (is_4700x2_spine)
+               port->ext_portnum = int2ext_map_sfb4700x2[chipnum][portnum];
        else
                port->ext_portnum = int2ext_map_slb8[chipnum][portnum];
 }
 
-static int add_chassis(ibnd_fabric_t * fabric)
+static int add_chassis(chassis_scan_t * chassis_scan)
 {
-       if (!(fabric->current_chassis = calloc(1, sizeof(ibnd_chassis_t)))) {
+       if (!(chassis_scan->current_chassis =
+             calloc(1, sizeof(ibnd_chassis_t)))) {
                IBND_ERROR("OOM: failed to allocate chassis object\n");
-               return (-1);
+               return -1;
        }
 
-       if (fabric->first_chassis == NULL) {
-               fabric->first_chassis = fabric->current_chassis;
-               fabric->last_chassis = fabric->current_chassis;
+       if (chassis_scan->first_chassis == NULL) {
+               chassis_scan->first_chassis = chassis_scan->current_chassis;
+               chassis_scan->last_chassis = chassis_scan->current_chassis;
        } else {
-               fabric->last_chassis->next = fabric->current_chassis;
-               fabric->last_chassis = fabric->current_chassis;
+               chassis_scan->last_chassis->next =
+                   chassis_scan->current_chassis;
+               chassis_scan->last_chassis = chassis_scan->current_chassis;
        }
-       return (0);
+       return 0;
 }
 
 static void add_node_to_chassis(ibnd_chassis_t * chassis, ibnd_node_t * node)
@@ -821,103 +1021,95 @@ static void add_node_to_chassis(ibnd_chassis_t * chassis, ibnd_node_t * node)
 int group_nodes(ibnd_fabric_t * fabric)
 {
        ibnd_node_t *node;
-       int dist;
        int chassisnum = 0;
        ibnd_chassis_t *chassis;
+       ibnd_chassis_t *ch, *ch_next;
+       chassis_scan_t chassis_scan;
 
-       fabric->first_chassis = NULL;
-       fabric->current_chassis = NULL;
+       chassis_scan.first_chassis = NULL;
+       chassis_scan.current_chassis = NULL;
+       chassis_scan.last_chassis = NULL;
 
        /* first pass on switches and build for every Voltaire node */
        /* an appropriate chassis record (slotnum and position) */
        /* according to internal connectivity */
        /* not very efficient but clear code so... */
-       for (dist = 0; dist <= fabric->maxhops_discovered; dist++) {
-               for (node = fabric->nodesdist[dist]; node; node = node->dnext) {
-                       if (mad_get_field(node->info, 0,
-                                         IB_NODE_VENDORID_F) == VTR_VENDOR_ID)
-                               if (fill_voltaire_chassis_record(node))
-                                       return (-1);
-               }
+       for (node = fabric->switches; node; node = node->type_next) {
+               if (mad_get_field(node->info, 0,
+                                 IB_NODE_VENDORID_F) == VTR_VENDOR_ID
+                   && fill_voltaire_chassis_record(node))
+                       goto cleanup;
        }
 
        /* separate every Voltaire chassis from each other and build linked list of them */
        /* algorithm: catch spine and find all surrounding nodes */
-       for (dist = 0; dist <= fabric->maxhops_discovered; dist++) {
-               for (node = fabric->nodesdist[dist]; node; node = node->dnext) {
-                       if (mad_get_field(node->info, 0,
-                                         IB_NODE_VENDORID_F) != VTR_VENDOR_ID)
-                               continue;
-                       if (!node->ch_found
-                           || (node->chassis && node->chassis->chassisnum)
-                           || !is_spine(node))
-                               continue;
-                       if (add_chassis(fabric))
-                               return (-1);
-                       fabric->current_chassis->chassisnum = ++chassisnum;
-                       if (build_chassis(node, fabric->current_chassis))
-                               return (-1);
-               }
+       for (node = fabric->switches; node; node = node->type_next) {
+               if (mad_get_field(node->info, 0,
+                                 IB_NODE_VENDORID_F) != VTR_VENDOR_ID)
+                       continue;
+               if (!node->ch_found
+                   || (node->chassis && node->chassis->chassisnum)
+                   || !is_spine(node))
+                       continue;
+               if (add_chassis(&chassis_scan))
+                       goto cleanup;
+               chassis_scan.current_chassis->chassisnum = ++chassisnum;
+               if (build_chassis(node, chassis_scan.current_chassis))
+                       goto cleanup;
        }
 
        /* now make pass on nodes for chassis which are not Voltaire */
        /* grouped by common SystemImageGUID */
-       for (dist = 0; dist <= fabric->maxhops_discovered; dist++) {
-               for (node = fabric->nodesdist[dist]; node; node = node->dnext) {
-                       if (mad_get_field(node->info, 0,
-                                         IB_NODE_VENDORID_F) == VTR_VENDOR_ID)
-                               continue;
-                       if (mad_get_field64(node->info, 0,
-                                           IB_NODE_SYSTEM_GUID_F)) {
-                               chassis =
-                                   find_chassisguid(fabric,
-                                                    (ibnd_node_t *) node);
-                               if (chassis)
-                                       chassis->nodecount++;
-                               else {
-                                       /* Possible new chassis */
-                                       if (add_chassis(fabric))
-                                               return (-1);
-                                       fabric->current_chassis->chassisguid =
-                                           get_chassisguid((ibnd_node_t *)
-                                                           node);
-                                       fabric->current_chassis->nodecount = 1;
-                               }
+       for (node = fabric->nodes; node; node = node->next) {
+               if (mad_get_field(node->info, 0,
+                                 IB_NODE_VENDORID_F) == VTR_VENDOR_ID)
+                       continue;
+               if (mad_get_field64(node->info, 0, IB_NODE_SYSTEM_GUID_F)) {
+                       chassis = find_chassisguid(fabric, node);
+                       if (chassis)
+                               chassis->nodecount++;
+                       else {
+                               /* Possible new chassis */
+                               if (add_chassis(&chassis_scan))
+                                       goto cleanup;
+                               chassis_scan.current_chassis->chassisguid =
+                                   get_chassisguid(node);
+                               chassis_scan.current_chassis->nodecount = 1;
+                               if (!fabric->chassis)
+                                       fabric->chassis = chassis_scan.first_chassis;
                        }
                }
        }
 
        /* now, make another pass to see which nodes are part of chassis */
        /* (defined as chassis->nodecount > 1) */
-       for (dist = 0; dist <= MAXHOPS;) {
-               for (node = fabric->nodesdist[dist]; node; node = node->dnext) {
-                       if (mad_get_field(node->info, 0,
-                                         IB_NODE_VENDORID_F) == VTR_VENDOR_ID)
-                               continue;
-                       if (mad_get_field64(node->info, 0,
-                                           IB_NODE_SYSTEM_GUID_F)) {
-                               chassis =
-                                   find_chassisguid(fabric,
-                                                    (ibnd_node_t *) node);
-                               if (chassis && chassis->nodecount > 1) {
-                                       if (!chassis->chassisnum)
-                                               chassis->chassisnum =
-                                                   ++chassisnum;
-                                       if (!node->ch_found) {
-                                               node->ch_found = 1;
-                                               add_node_to_chassis(chassis,
-                                                                   (ibnd_node_t
-                                                                    *) node);
-                                       }
+       for (node = fabric->nodes; node; node = node->next) {
+               if (mad_get_field(node->info, 0,
+                                 IB_NODE_VENDORID_F) == VTR_VENDOR_ID)
+                       continue;
+               if (mad_get_field64(node->info, 0, IB_NODE_SYSTEM_GUID_F)) {
+                       chassis = find_chassisguid(fabric, node);
+                       if (chassis && chassis->nodecount > 1) {
+                               if (!chassis->chassisnum)
+                                       chassis->chassisnum = ++chassisnum;
+                               if (!node->ch_found) {
+                                       node->ch_found = 1;
+                                       add_node_to_chassis(chassis, node);
                                }
                        }
                }
-               if (dist == fabric->maxhops_discovered)
-                       dist = MAXHOPS; /* skip to CAs */
-               else
-                       dist++;
        }
 
-       fabric->chassis = fabric->first_chassis;
-       return (0);
+       fabric->chassis = chassis_scan.first_chassis;
+       return 0;
+
+cleanup:
+       ch = chassis_scan.first_chassis;
+       while (ch) {
+               ch_next = ch->next;
+               free(ch);
+               ch = ch_next;
+       }
+       fabric->chassis = NULL;
+       return -1;
 }
index 21910467827ee780c5af961b8d1efba83e32d7d9..f8e0ee2b583fe67517169ce5ff8d2525fb2ac59e 100644 (file)
@@ -70,6 +70,9 @@
 #define VTR_DEVID_SFB2004              0x5a40
 #define VTR_DEVID_ISR2004              0x5a41
 #define VTR_DEVID_SRB2004              0x5a42
+#define VTR_DEVID_SLB4018              0x5a5b
+#define VTR_DEVID_SFB4700              0x5a5c
+#define VTR_DEVID_SFB4700X2            0x5a5d
 
 /* Vendor IDs (for chassis based systems) */
 #define VTR_VENDOR_ID                  0x8f1   /* Voltaire */
@@ -78,7 +81,8 @@
 #define XS_VENDOR_ID                   0x1397  /* Xsigo */
 
 enum ibnd_chassis_type {
-       UNRESOLVED_CT, ISR9288_CT, ISR9096_CT, ISR2012_CT, ISR2004_CT
+       UNRESOLVED_CT, ISR9288_CT, ISR9096_CT, ISR2012_CT, ISR2004_CT,
+       ISR4700_CT
 };
 enum ibnd_chassis_slot_type { UNRESOLVED_CS, LINE_CS, SPINE_CS, SRBD_CS };
 
index 97e369ca12cc50a12fc2d2f063dd9f09f97dad57..f525d71bf71cfacab2e7e30a4d826d959e3e856c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004-2007 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2004-2009 Voltaire Inc.  All rights reserved.
  * Copyright (c) 2007 Xsigo Systems Inc.  All rights reserved.
  * Copyright (c) 2008 Lawrence Livermore National Laboratory
  *
  */
 
 #if HAVE_CONFIG_H
-#  include <config.h>
+#include <config.h>
 #endif                         /* HAVE_CONFIG_H */
 
 #define _GNU_SOURCE
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
-#include <stdarg.h>
-#include <time.h>
 #include <string.h>
-#include <getopt.h>
 #include <errno.h>
 #include <inttypes.h>
 
 #include "internal.h"
 #include "chassis.h"
 
-static int show_progress = 0;
-int ibdebug;
+/* forward declare */
+static int query_node_info(smp_engine_t * engine, ib_portid_t * portid,
+                          ibnd_node_t * node);
 
-void decode_port_info(ibnd_port_t * port)
+static int recv_switch_info(smp_engine_t * engine, ibnd_smp_t * smp,
+                           uint8_t * mad, void *cb_data)
 {
-       port->base_lid = (uint16_t) mad_get_field(port->info, 0, IB_PORT_LID_F);
-       port->lmc = (uint8_t) mad_get_field(port->info, 0, IB_PORT_LMC_F);
+       uint8_t *switch_info = mad + IB_SMP_DATA_OFFS;
+       ibnd_node_t *node = cb_data;
+       memcpy(node->switchinfo, switch_info, sizeof(node->switchinfo));
+       mad_decode_field(node->switchinfo, IB_SW_ENHANCED_PORT0_F,
+                        &node->smaenhsp0);
+       return 0;
+}
+
+static int query_switch_info(smp_engine_t * engine, ib_portid_t * portid,
+                            ibnd_node_t * node)
+{
+       node->smaenhsp0 = 0;    /* assume base SP0 */
+       return issue_smp(engine, portid, IB_ATTR_SWITCH_INFO, 0,
+                        recv_switch_info, node);
+}
+
+static int add_port_to_dpath(ib_dr_path_t * path, int nextport)
+{
+       if (path->cnt > sizeof(path->p) - 1)
+               return -1;
+       ++path->cnt;
+       path->p[path->cnt] = (uint8_t) nextport;
+       return path->cnt;
+}
+
+static int extend_dpath(smp_engine_t * engine, ib_portid_t * portid,
+                       int nextport)
+{
+       ibnd_scan_t *scan = engine->user_data;
+       ibnd_fabric_t *fabric = scan->fabric;
+
+       if (scan->cfg->max_hops &&
+           fabric->maxhops_discovered >= scan->cfg->max_hops)
+               return 0;
+
+       if (portid->lid) {
+               /* If we were LID routed we need to set up the drslid */
+               if (!scan->selfportid.lid)
+                       if (ib_resolve_self_via(&scan->selfportid, NULL, NULL,
+                                               scan->ibmad_port) < 0) {
+                               IBND_ERROR("Failed to resolve self\n");
+                               return -1;
+                       }
+               portid->drpath.drslid = (uint16_t) scan->selfportid.lid;
+               portid->drpath.drdlid = 0xFFFF;
+       }
+
+       if (add_port_to_dpath(&portid->drpath, nextport) < 0) {
+               IBND_ERROR("add port %d to DR path failed; %s\n", nextport,
+                          portid2str(portid));
+               return -1;
+       }
+
+       if ((unsigned) portid->drpath.cnt > fabric->maxhops_discovered)
+               fabric->maxhops_discovered = portid->drpath.cnt;
+
+       return 1;
+}
+
+static int recv_node_desc(smp_engine_t * engine, ibnd_smp_t * smp,
+                         uint8_t * mad, void *cb_data)
+{
+       uint8_t *node_desc = mad + IB_SMP_DATA_OFFS;
+       ibnd_node_t *node = cb_data;
+       memcpy(node->nodedesc, node_desc, sizeof(node->nodedesc));
+       return 0;
 }
 
-static int get_port_info(struct ibmad_port *ibmad_port,
-                        ibnd_fabric_t * fabric, ibnd_port_t * port,
-                        int portnum, ib_portid_t * portid)
+static int query_node_desc(smp_engine_t * engine, ib_portid_t * portid,
+                          ibnd_node_t * node)
+{
+       return issue_smp(engine, portid, IB_ATTR_NODE_DESC, 0,
+                        recv_node_desc, node);
+}
+
+static void debug_port(ib_portid_t * portid, ibnd_port_t * port)
 {
        char width[64], speed[64];
        int iwidth;
        int ispeed;
 
-       port->portnum = portnum;
        iwidth = mad_get_field(port->info, 0, IB_PORT_LINK_WIDTH_ACTIVE_F);
        ispeed = mad_get_field(port->info, 0, IB_PORT_LINK_SPEED_ACTIVE_F);
-
-       if (!smp_query_via(port->info, portid, IB_ATTR_PORT_INFO,
-                          portnum, 0, ibmad_port))
-               return -1;
-
-       decode_port_info(port);
-
        IBND_DEBUG
            ("portid %s portnum %d: base lid %d state %d physstate %d %s %s\n",
-            portid2str(portid), portnum, port->base_lid,
+            portid2str(portid), port->portnum, port->base_lid,
             mad_get_field(port->info, 0, IB_PORT_STATE_F),
             mad_get_field(port->info, 0, IB_PORT_PHYS_STATE_F),
             mad_dump_val(IB_PORT_LINK_WIDTH_ACTIVE_F, width, 64, &iwidth),
             mad_dump_val(IB_PORT_LINK_SPEED_ACTIVE_F, speed, 64, &ispeed));
-       return 0;
-}
-
-/*
- * Returns -1 if error.
- */
-static int query_node_info(struct ibmad_port *ibmad_port,
-                          ibnd_fabric_t * fabric, ibnd_node_t * node,
-                          ib_portid_t * portid)
-{
-       if (!smp_query_via(&(node->info), portid, IB_ATTR_NODE_INFO, 0, 0,
-                          ibmad_port))
-               return -1;
-
-       /* decode just a couple of fields for quicker reference. */
-       mad_decode_field(node->info, IB_NODE_GUID_F, &(node->guid));
-       mad_decode_field(node->info, IB_NODE_TYPE_F, &(node->type));
-       mad_decode_field(node->info, IB_NODE_NPORTS_F, &(node->numports));
-
-       return (0);
 }
 
-/*
- * Returns 0 if non switch node is found, 1 if switch is found, -1 if error.
- */
-static int query_node(struct ibmad_port *ibmad_port, ibnd_fabric_t * fabric,
-                     ibnd_node_t * node, ibnd_port_t * port,
-                     ib_portid_t * portid)
+static int recv_port_info(smp_engine_t * engine, ibnd_smp_t * smp,
+                         uint8_t * mad, void *cb_data)
 {
-       int rc = 0;
-       void *nd = node->nodedesc;
-
-       if ((rc = query_node_info(ibmad_port, fabric, node, portid)) != 0)
-               return rc;
-
-       port->portnum = mad_get_field(node->info, 0, IB_NODE_LOCAL_PORT_F);
-       port->guid = mad_get_field64(node->info, 0, IB_NODE_PORT_GUID_F);
+       ibnd_fabric_t *fabric = ((ibnd_scan_t *) engine->user_data)->fabric;
+       ibnd_node_t *node = cb_data;
+       ibnd_port_t *port;
+       uint8_t *port_info = mad + IB_SMP_DATA_OFFS;
+       uint8_t port_num, local_port;
 
-       if (!smp_query_via(nd, portid, IB_ATTR_NODE_DESC, 0, 0, ibmad_port))
-               return -1;
+       port_num = (uint8_t) mad_get_field(mad, 0, IB_MAD_ATTRMOD_F);
+       local_port = (uint8_t) mad_get_field(port_info, 0, IB_PORT_LOCAL_PORT_F);
 
-       if (!smp_query_via(port->info, portid, IB_ATTR_PORT_INFO, 0, 0,
-                          ibmad_port))
-               return -1;
-       decode_port_info(port);
+       /* this may have been created before */
+       port = node->ports[port_num];
+       if (!port) {
+               port = node->ports[port_num] = calloc(1, sizeof(*port));
+               if (!port) {
+                       IBND_ERROR("Failed to allocate port\n");
+                       return -1;
+               }
+               port->guid =
+                   mad_get_field64(node->info, 0, IB_NODE_PORT_GUID_F);
+       }
 
-       if (node->type != IB_NODE_SWITCH)
-               return 0;
+       memcpy(port->info, port_info, sizeof(port->info));
+       port->node = node;
+       port->portnum = port_num;
+       port->ext_portnum = 0;
+       port->base_lid = (uint16_t) mad_get_field(port->info, 0, IB_PORT_LID_F);
+       port->lmc = (uint8_t) mad_get_field(port->info, 0, IB_PORT_LMC_F);
 
-       node->smalid = port->base_lid;
-       node->smalmc = port->lmc;
+       if (port_num == 0) {
+               node->smalid = port->base_lid;
+               node->smalmc = port->lmc;
+       } else if (node->type == IB_NODE_SWITCH) {
+               port->base_lid = node->smalid;
+               port->lmc = node->smalmc;
+       }
 
-       /* after we have the sma information find out the real PortInfo for this port */
-       if (!smp_query_via(port->info, portid, IB_ATTR_PORT_INFO,
-                          port->portnum, 0, ibmad_port))
-               return -1;
-       decode_port_info(port);
+       add_to_portguid_hash(port, fabric->portstbl);
 
-       port->base_lid = (uint16_t) node->smalid;       /* LID is still defined by port 0 */
-       port->lmc = (uint8_t) node->smalmc;
+       debug_port(&smp->path, port);
 
-       if (!smp_query_via(node->switchinfo, portid, IB_ATTR_SWITCH_INFO, 0, 0,
-                          ibmad_port))
-               node->smaenhsp0 = 0;    /* assume base SP0 */
-       else
-               mad_decode_field(node->switchinfo, IB_SW_ENHANCED_PORT0_F,
-                                &node->smaenhsp0);
+       if (port_num && mad_get_field(port->info, 0, IB_PORT_PHYS_STATE_F)
+           == IB_PORT_PHYS_STATE_LINKUP
+           && ((node->type == IB_NODE_SWITCH && port_num != local_port) ||
+               (node == fabric->from_node && port_num == local_port))) {
+               ib_portid_t path = smp->path;
+               if (extend_dpath(engine, &path, port_num) > 0)
+                       query_node_info(engine, &path, node);
+       }
 
-       IBND_DEBUG("portid %s: got switch node %" PRIx64 " '%s'\n",
-                  portid2str(portid), node->guid, node->nodedesc);
        return 0;
 }
 
-static int add_port_to_dpath(ib_dr_path_t * path, int nextport)
+static int query_port_info(smp_engine_t * engine, ib_portid_t * portid,
+                          ibnd_node_t * node, int portnum)
 {
-       if (path->cnt + 2 >= sizeof(path->p)) {
-               IBND_ERROR("DR path has grown too long\n");
-               return -1;
-       }
-       ++path->cnt;
-       path->p[path->cnt] = (uint8_t) nextport;
-       return path->cnt;
+       IBND_DEBUG("Query Port Info; %s (0x%" PRIx64 "):%d\n",
+                  portid2str(portid), node->guid, portnum);
+       return issue_smp(engine, portid, IB_ATTR_PORT_INFO, portnum,
+                        recv_port_info, node);
 }
 
-static void retract_dpath(ib_portid_t * path)
+static ibnd_node_t *create_node(smp_engine_t * engine, ib_portid_t * path,
+                               uint8_t * node_info)
 {
-       path->drpath.cnt--;     /* restore path */
-       if (path->drpath.cnt == 0 && path->lid) {
-               /* return to lid based routing on this path */
-               path->drpath.drslid = 0;
-               path->drpath.drdlid = 0;
+       ibnd_fabric_t *fabric = ((ibnd_scan_t *) engine->user_data)->fabric;
+       ibnd_node_t *rc = calloc(1, sizeof(*rc));
+       if (!rc) {
+               IBND_ERROR("OOM: node creation failed\n");
+               return NULL;
        }
-}
 
-static int extend_dpath(struct ibmad_port *ibmad_port, ibnd_fabric_t * fabric,
-                       ib_portid_t * portid, int nextport)
-{
-       int rc = 0;
+       /* decode just a couple of fields for quicker reference. */
+       mad_decode_field(node_info, IB_NODE_GUID_F, &rc->guid);
+       mad_decode_field(node_info, IB_NODE_TYPE_F, &rc->type);
+       mad_decode_field(node_info, IB_NODE_NPORTS_F, &rc->numports);
+
+       rc->ports = calloc(rc->numports + 1, sizeof(*rc->ports));
+       if (!rc->ports) {
+               free(rc);
+               IBND_ERROR("OOM: Failed to allocate the ports array\n");
+               return NULL;
+       }
 
-       if (portid->lid) {
-               /* If we were LID routed we need to set up the drslid */
-               if (!fabric->selfportid.lid)
-                       if (ib_resolve_self_via(&fabric->selfportid, NULL, NULL,
-                                               ibmad_port) < 0) {
-                               IBND_ERROR("Failed to resolve self\n");
-                               return -1;
-                       }
+       rc->path_portid = *path;
+       memcpy(rc->info, node_info, sizeof(rc->info));
 
-               portid->drpath.drslid = (uint16_t) fabric->selfportid.lid;
-               portid->drpath.drdlid = 0xFFFF;
-       }
+       add_to_nodeguid_hash(rc, fabric->nodestbl);
 
-       rc = add_port_to_dpath(&portid->drpath, nextport);
+       /* add this to the all nodes list */
+       rc->next = fabric->nodes;
+       fabric->nodes = rc;
 
-       if ((rc != -1) && (portid->drpath.cnt > fabric->maxhops_discovered))
-               fabric->maxhops_discovered = portid->drpath.cnt;
-       return (rc);
+       add_to_type_list(rc, fabric);
+
+       return rc;
+}
+
+static int get_last_port(ib_portid_t * path)
+{
+       return path->drpath.p[path->drpath.cnt];
+}
+
+static void link_ports(ibnd_node_t * node, ibnd_port_t * port,
+                      ibnd_node_t * remotenode, ibnd_port_t * remoteport)
+{
+       IBND_DEBUG("linking: 0x%" PRIx64 " %p->%p:%u and 0x%" PRIx64
+                  " %p->%p:%u\n", node->guid, node, port, port->portnum,
+                  remotenode->guid, remotenode, remoteport,
+                  remoteport->portnum);
+       if (port->remoteport)
+               port->remoteport->remoteport = NULL;
+       if (remoteport->remoteport)
+               remoteport->remoteport->remoteport = NULL;
+       port->remoteport = remoteport;
+       remoteport->remoteport = port;
 }
 
 static void dump_endnode(ib_portid_t * path, char *prompt,
                         ibnd_node_t * node, ibnd_port_t * port)
 {
        char type[64];
-       if (!show_progress)
-               return;
-
-       mad_dump_node_type(type, 64, &(node->type), sizeof(int));
-       printf("%s -> %s %s {%016" PRIx64 "} portnum %d base lid %d-%d\"%s\"\n",
+       mad_dump_node_type(type, sizeof(type), &node->type, sizeof(int));
+       printf("%s -> %s %s {%016" PRIx64 "} portnum %d lid %d-%d \"%s\"\n",
               portid2str(path), prompt, type, node->guid,
               node->type == IB_NODE_SWITCH ? 0 : port->portnum,
-              port->base_lid,
-              port->base_lid + (1 << port->lmc) - 1, node->nodedesc);
+              port->base_lid, port->base_lid + (1 << port->lmc) - 1,
+              node->nodedesc);
 }
 
-static ibnd_node_t *find_existing_node(ibnd_fabric_t * fabric,
-                                      ibnd_node_t * new)
+static int recv_node_info(smp_engine_t * engine, ibnd_smp_t * smp,
+                         uint8_t * mad, void *cb_data)
 {
-       int hash = HASHGUID(new->guid) % HTSZ;
+       ibnd_scan_t *scan = engine->user_data;
+       ibnd_fabric_t *fabric = scan->fabric;
+       int i = 0;
+       uint8_t *node_info = mad + IB_SMP_DATA_OFFS;
+       ibnd_node_t *rem_node = cb_data;
        ibnd_node_t *node;
+       int node_is_new = 0;
+       uint64_t node_guid = mad_get_field64(node_info, 0, IB_NODE_GUID_F);
+       uint64_t port_guid = mad_get_field64(node_info, 0, IB_NODE_PORT_GUID_F);
+       int port_num = mad_get_field(node_info, 0, IB_NODE_LOCAL_PORT_F);
+       ibnd_port_t *port = NULL;
 
-       for (node = fabric->nodestbl[hash]; node; node = node->htnext)
-               if (node->guid == new->guid)
-                       return node;
+       node = ibnd_find_node_guid(fabric, node_guid);
+       if (!node) {
+               node = create_node(engine, &smp->path, node_info);
+               if (!node)
+                       return -1;
+               node_is_new = 1;
+       }
+       IBND_DEBUG("Found %s node GUID 0x%" PRIx64 " (%s)\n",
+                  node_is_new ? "new" : "old", node->guid,
+                  portid2str(&smp->path));
 
-       return NULL;
-}
+       port = node->ports[port_num];
+       if (!port) {
+               /* If we have not see this port before create a shell for it */
+               port = node->ports[port_num] = calloc(1, sizeof(*port));
+               port->node = node;
+               port->portnum = port_num;
+       }
+       port->guid = port_guid;
+
+       if (scan->cfg->show_progress)
+               dump_endnode(&smp->path, node_is_new ? "new" : "known",
+                            node, port);
+
+       if (rem_node == NULL)   /* this is the start node */
+               fabric->from_node = node;
+       else {
+               /* link ports... */
+               int rem_port_num = get_last_port(&smp->path);
+
+               if (!rem_node->ports[rem_port_num]) {
+                       IBND_ERROR("Internal Error; "
+                                  "Node(%p) 0x%" PRIx64
+                                  " Port %d no port created!?!?!?\n\n",
+                                  rem_node, rem_node->guid, rem_port_num);
+                       return -1;
+               }
 
-ibnd_node_t *ibnd_find_node_guid(ibnd_fabric_t * fabric, uint64_t guid)
-{
-       int hash = HASHGUID(guid) % HTSZ;
-       ibnd_node_t *node;
+               link_ports(node, port, rem_node, rem_node->ports[rem_port_num]);
+       }
 
-       if (!fabric) {
-               IBND_DEBUG("fabric parameter NULL\n");
-               return (NULL);
+       if (node_is_new) {
+               query_node_desc(engine, &smp->path, node);
+
+               if (node->type == IB_NODE_SWITCH) {
+                       query_switch_info(engine, &smp->path, node);
+                       for (i = 0; i <= node->numports; i++)
+                               query_port_info(engine, &smp->path, node, i);
+               }
        }
 
-       for (node = fabric->nodestbl[hash]; node; node = node->htnext)
-               if (node->guid == guid)
-                       return (ibnd_node_t *) node;
+       if (node->type != IB_NODE_SWITCH)
+               query_port_info(engine, &smp->path, node, port_num);
 
-       return NULL;
+       return 0;
 }
 
-static int _check_ibmad_port(struct ibmad_port *ibmad_port)
+static int query_node_info(smp_engine_t * engine, ib_portid_t * portid,
+                          ibnd_node_t * node)
 {
-       if (!ibmad_port) {
-               IBND_DEBUG("ibmad_port must be specified\n");
-               return (-1);
-       }
-       if (mad_rpc_class_agent(ibmad_port, IB_SMI_CLASS) == -1
-           || mad_rpc_class_agent(ibmad_port, IB_SMI_DIRECT_CLASS) == -1) {
-               IBND_DEBUG("ibmad_port must be opened with "
-                          "IB_SMI_CLASS && IB_SMI_DIRECT_CLASS\n");
-               return (-1);
-       }
-       return (0);
+       IBND_DEBUG("Query Node Info; %s\n", portid2str(portid));
+       return issue_smp(engine, portid, IB_ATTR_NODE_INFO, 0,
+                        recv_node_info, node);
 }
 
-ibnd_node_t *ibnd_update_node(struct ibmad_port * ibmad_port,
-                             ibnd_fabric_t * fabric, ibnd_node_t * node)
+ibnd_node_t *ibnd_find_node_guid(ibnd_fabric_t * fabric, uint64_t guid)
 {
-       char portinfo_port0[IB_SMP_DATA_SIZE];
-       void *nd = node->nodedesc;
-       int p = 0;
-
-       if (_check_ibmad_port(ibmad_port) < 0)
-               return (NULL);
+       int hash = HASHGUID(guid) % HTSZ;
+       ibnd_node_t *node;
 
        if (!fabric) {
                IBND_DEBUG("fabric parameter NULL\n");
-               return (NULL);
-       }
-
-       if (!node) {
-               IBND_DEBUG("node parameter NULL\n");
-               return (NULL);
-       }
-
-       if (query_node_info(ibmad_port, fabric, node, &(node->path_portid)))
-               return (NULL);
-
-       if (!smp_query_via(nd, &(node->path_portid), IB_ATTR_NODE_DESC, 0, 0,
-                          ibmad_port))
-               return (NULL);
-
-       /* update all the port info's */
-       for (p = 1; p >= node->numports; p++) {
-               get_port_info(ibmad_port, fabric, node->ports[p],
-                             p, &(node->path_portid));
+               return NULL;
        }
 
-       if (node->type != IB_NODE_SWITCH)
-               goto done;
-
-       if (!smp_query_via
-           (portinfo_port0, &(node->path_portid), IB_ATTR_PORT_INFO, 0, 0,
-            ibmad_port))
-               return (NULL);
-
-       node->smalid = mad_get_field(portinfo_port0, 0, IB_PORT_LID_F);
-       node->smalmc = mad_get_field(portinfo_port0, 0, IB_PORT_LMC_F);
-
-       if (!smp_query_via(node->switchinfo, &(node->path_portid),
-                          IB_ATTR_SWITCH_INFO, 0, 0, ibmad_port))
-               node->smaenhsp0 = 0;    /* assume base SP0 */
-       else
-               mad_decode_field(node->switchinfo, IB_SW_ENHANCED_PORT0_F,
-                                &node->smaenhsp0);
+       for (node = fabric->nodestbl[hash]; node; node = node->htnext)
+               if (node->guid == guid)
+                       return node;
 
-done:
-       return (node);
+       return NULL;
 }
 
 ibnd_node_t *ibnd_find_node_dr(ibnd_fabric_t * fabric, char *dr_str)
@@ -333,33 +390,32 @@ ibnd_node_t *ibnd_find_node_dr(ibnd_fabric_t * fabric, char *dr_str)
 
        if (!fabric) {
                IBND_DEBUG("fabric parameter NULL\n");
-               return (NULL);
+               return NULL;
        }
 
        rc = fabric->from_node;
 
-       if (str2drpath(&path, dr_str, 0, 0) == -1) {
-               return (NULL);
-       }
+       if (str2drpath(&path, dr_str, 0, 0) == -1)
+               return NULL;
 
        for (i = 0; i <= path.cnt; i++) {
                ibnd_port_t *remote_port = NULL;
                if (path.p[i] == 0)
                        continue;
                if (!rc->ports)
-                       return (NULL);
+                       return NULL;
 
                remote_port = rc->ports[path.p[i]]->remoteport;
                if (!remote_port)
-                       return (NULL);
+                       return NULL;
 
                rc = remote_port->node;
        }
 
-       return (rc);
+       return rc;
 }
 
-static void add_to_nodeguid_hash(ibnd_node_t * node, ibnd_node_t * hash[])
+void add_to_nodeguid_hash(ibnd_node_t * node, ibnd_node_t * hash[])
 {
        int hash_idx = HASHGUID(node->guid) % HTSZ;
 
@@ -367,7 +423,7 @@ static void add_to_nodeguid_hash(ibnd_node_t * node, ibnd_node_t * hash[])
        hash[hash_idx] = node;
 }
 
-static void add_to_portguid_hash(ibnd_port_t * port, ibnd_port_t * hash[])
+void add_to_portguid_hash(ibnd_port_t * port, ibnd_port_t * hash[])
 {
        int hash_idx = HASHGUID(port->guid) % HTSZ;
 
@@ -375,7 +431,7 @@ static void add_to_portguid_hash(ibnd_port_t * port, ibnd_port_t * hash[])
        hash[hash_idx] = port;
 }
 
-static void add_to_type_list(ibnd_node_t * node, ibnd_fabric_t * fabric)
+void add_to_type_list(ibnd_node_t * node, ibnd_fabric_t * fabric)
 {
        switch (node->type) {
        case IB_NODE_CA:
@@ -393,291 +449,106 @@ static void add_to_type_list(ibnd_node_t * node, ibnd_fabric_t * fabric)
        }
 }
 
-static void add_to_nodedist(ibnd_node_t * node, ibnd_fabric_t * fabric)
-{
-       int dist = node->dist;
-       if (node->type != IB_NODE_SWITCH)
-               dist = MAXHOPS; /* special Ca list */
-
-       node->dnext = fabric->nodesdist[dist];
-       fabric->nodesdist[dist] = node;
-}
-
-static ibnd_node_t *create_node(ibnd_fabric_t * fabric,
-                               ibnd_node_t * temp, ib_portid_t * path,
-                               int dist)
-{
-       ibnd_node_t *node;
-
-       node = malloc(sizeof(*node));
-       if (!node) {
-               IBND_ERROR("OOM: node creation failed\n");
-               return (NULL);
-       }
-
-       memcpy(node, temp, sizeof(*node));
-       node->dist = dist;
-       node->path_portid = *path;
-
-       add_to_nodeguid_hash(node, fabric->nodestbl);
-
-       /* add this to the all nodes list */
-       node->next = fabric->nodes;
-       fabric->nodes = (ibnd_node_t *) node;
-
-       add_to_type_list(node, fabric);
-       add_to_nodedist(node, fabric);
-
-       return node;
-}
-
-static struct ibnd_port *find_existing_port_node(ibnd_node_t * node,
-                                                ibnd_port_t * port)
-{
-       if (port->portnum > node->numports || node->ports == NULL)
-               return (NULL);
-
-       return (node->ports[port->portnum]);
-}
-
-static struct ibnd_port *add_port_to_node(ibnd_fabric_t * fabric,
-                                         ibnd_node_t * node,
-                                         ibnd_port_t * temp)
+static int set_config(struct ibnd_config *config, struct ibnd_config *cfg)
 {
-       ibnd_port_t *port;
-
-       if (node->ports == NULL) {
-               node->ports = calloc(sizeof(*node->ports), node->numports + 1);
-               if (!node->ports) {
-                       IBND_ERROR("Failed to allocate the ports array\n");
-                       return (NULL);
-               }
-       }
-
-       port = malloc(sizeof(*port));
-       if (!port) {
-               IBND_ERROR("Failed to allocate port\n");
-               return NULL;
-       }
-
-       memcpy(port, temp, sizeof(*port));
-       port->node = (ibnd_node_t *) node;
-       port->ext_portnum = 0;
+       if (!config)
+               return (-EINVAL);
 
-       node->ports[temp->portnum] = (ibnd_port_t *) port;
+       if (cfg)
+               memcpy(config, cfg, sizeof(*config));
 
-       add_to_portguid_hash(port, fabric->portstbl);
-       return port;
-}
+       if (!config->max_smps)
+               config->max_smps = DEFAULT_MAX_SMP_ON_WIRE;
+       if (!config->timeout_ms)
+               config->timeout_ms = DEFAULT_TIMEOUT;
+       if (!config->retries)
+               config->retries = DEFAULT_RETRIES;
 
-static void link_ports(ibnd_node_t * node, ibnd_port_t * port,
-                      ibnd_node_t * remotenode, ibnd_port_t * remoteport)
-{
-       IBND_DEBUG("linking: 0x%" PRIx64 " %p->%p:%u and 0x%" PRIx64
-                  " %p->%p:%u\n", node->guid, node, port, port->portnum,
-                  remotenode->guid, remotenode, remoteport,
-                  remoteport->portnum);
-       if (port->remoteport)
-               port->remoteport->remoteport = NULL;
-       if (remoteport->remoteport)
-               remoteport->remoteport->remoteport = NULL;
-       port->remoteport = (ibnd_port_t *) remoteport;
-       remoteport->remoteport = (ibnd_port_t *) port;
-}
-
-static int get_remote_node(struct ibmad_port *ibmad_port,
-                          ibnd_fabric_t * fabric, ibnd_node_t * node,
-                          ibnd_port_t * port, ib_portid_t * path,
-                          int portnum, int dist)
-{
-       int rc = 0;
-       ibnd_node_t node_buf;
-       ibnd_port_t port_buf;
-       ibnd_node_t *remotenode, *oldnode;
-       ibnd_port_t *remoteport, *oldport;
-
-       memset(&node_buf, 0, sizeof(node_buf));
-       memset(&port_buf, 0, sizeof(port_buf));
-
-       IBND_DEBUG("handle node %p port %p:%d dist %d\n", node, port, portnum,
-                  dist);
-
-       if (mad_get_field(port->info, 0, IB_PORT_PHYS_STATE_F)
-           != IB_PORT_PHYS_STATE_LINKUP)
-               return 1;       /* positive == non-fatal error */
-
-       if (extend_dpath(ibmad_port, fabric, path, portnum) < 0)
-               return -1;
-
-       if (query_node(ibmad_port, fabric, &node_buf, &port_buf, path)) {
-               IBND_ERROR("Query remote node (%s) failed, skipping port\n",
-                          portid2str(path));
-               retract_dpath(path);
-               return 1;       /* positive == non-fatal error */
-       }
-
-       oldnode = find_existing_node(fabric, &node_buf);
-       if (oldnode)
-               remotenode = oldnode;
-       else if (!(remotenode = create_node(fabric, &node_buf, path, dist + 1))) {
-               rc = -1;
-               goto error;
-       }
-
-       oldport = find_existing_port_node(remotenode, &port_buf);
-       if (oldport) {
-               remoteport = oldport;
-       } else if (!(remoteport = add_port_to_node(fabric, remotenode,
-                                                  &port_buf))) {
-               IBND_ERROR("OOM failed to add port to node\n");
-               rc = -1;
-               goto error;
-       }
-
-       dump_endnode(path, oldnode ? "known remote" : "new remote",
-                    remotenode, remoteport);
-
-       link_ports(node, port, remotenode, remoteport);
-
-error:
-       retract_dpath(path);
-       return (rc);
+       return (0);
 }
 
-ibnd_fabric_t *ibnd_discover_fabric(struct ibmad_port * ibmad_port,
-                                   ib_portid_t * from, int hops)
+ibnd_fabric_t *ibnd_discover_fabric(char * ca_name, int ca_port,
+                                   ib_portid_t * from,
+                                   struct ibnd_config *cfg)
 {
-       int rc = 0;
+       struct ibnd_config config = { 0 };
        ibnd_fabric_t *fabric = NULL;
        ib_portid_t my_portid = { 0 };
-       ibnd_node_t node_buf;
-       ibnd_port_t port_buf;
-       ibnd_node_t *node;
-       ibnd_port_t *port;
-       int i;
-       int dist = 0;
-       ib_portid_t *path;
-       int max_hops = MAXHOPS - 1;     /* default find everything */
-
-       if (_check_ibmad_port(ibmad_port) < 0)
-               return (NULL);
+       smp_engine_t engine;
+       ibnd_scan_t scan;
+       int nc = 2;
+       int mc[2] = { IB_SMI_CLASS, IB_SMI_DIRECT_CLASS };
 
-       /* if not everything how much? */
-       if (hops >= 0) {
-               max_hops = hops;
+       if (set_config(&config, cfg)) {
+               IBND_ERROR("Invalid ibnd_config\n");
+               return NULL;
        }
 
        /* If not specified start from "my" port */
        if (!from)
                from = &my_portid;
 
-       fabric = malloc(sizeof(*fabric));
-
+       fabric = calloc(1, sizeof(*fabric));
        if (!fabric) {
-               IBND_ERROR("OOM: failed to malloc ibnd_fabric_t\n");
-               return (NULL);
+               IBND_ERROR("OOM: failed to calloc ibnd_fabric_t\n");
+               return NULL;
        }
 
        memset(fabric, 0, sizeof(*fabric));
 
-       IBND_DEBUG("from %s\n", portid2str(from));
-
-       memset(&node_buf, 0, sizeof(node_buf));
-       memset(&port_buf, 0, sizeof(port_buf));
+       memset(&scan.selfportid, 0, sizeof(scan.selfportid));
+       scan.fabric = fabric;
+       scan.cfg = &config;
 
-       if (query_node(ibmad_port, fabric, &node_buf, &port_buf, from)) {
-               IBND_DEBUG("can't reach node %s\n", portid2str(from));
-               goto error;
+       if (smp_engine_init(&engine, ca_name, ca_port, &scan, &config)) {
+               free(fabric);
+               return (NULL);
        }
 
-       node = create_node(fabric, &node_buf, from, 0);
-       if (!node)
-               goto error;
-
-       fabric->from_node = (ibnd_node_t *) node;
-
-       port = add_port_to_node(fabric, node, &port_buf);
-       if (!port)
-               goto error;
-
-       if (node->type != IB_NODE_SWITCH) {
-               rc = get_remote_node(ibmad_port, fabric, node, port, from,
-                                    mad_get_field(node->info, 0,
-                                                  IB_NODE_LOCAL_PORT_F), 0);
-               if (rc < 0)
-                       goto error;
-               if (rc > 0)             /* non-fatal error, nothing more to be done */
-                       return ((ibnd_fabric_t *) fabric);
+       scan.ibmad_port = mad_rpc_open_port(ca_name, ca_port, mc, nc);
+       if (!scan.ibmad_port) {
+               IBND_ERROR("can't open MAD port (%s:%d)\n", ca_name, ca_port);
+               smp_engine_destroy(&engine);
+               return (NULL);
        }
+       mad_rpc_set_timeout(scan.ibmad_port, cfg->timeout_ms);
+       mad_rpc_set_retries(scan.ibmad_port, cfg->retries);
 
-       for (dist = 0; dist <= max_hops; dist++) {
-
-               for (node = fabric->nodesdist[dist]; node; node = node->dnext) {
-
-                       path = &node->path_portid;
-
-                       IBND_DEBUG("dist %d node %p\n", dist, node);
-                       dump_endnode(path, "processing", node, port);
-
-                       for (i = 1; i <= node->numports; i++) {
-                               if (i == mad_get_field(node->info, 0,
-                                                      IB_NODE_LOCAL_PORT_F))
-                                       continue;
-
-                               if (get_port_info(ibmad_port, fabric,
-                                                 &port_buf, i, path)) {
-                                       IBND_ERROR
-                                           ("can't reach node %s port %d\n",
-                                            portid2str(path), i);
-                                       continue;
-                               }
-
-                               port = find_existing_port_node(node, &port_buf);
-                               if (port)
-                                       continue;
-
-                               port =
-                                   add_port_to_node(fabric, node, &port_buf);
-                               if (!port)
-                                       goto error;
+       IBND_DEBUG("from %s\n", portid2str(from));
 
-                               /* If switch, set port GUID to node port GUID */
-                               if (node->type == IB_NODE_SWITCH) {
-                                       port->guid =
-                                           mad_get_field64(node->info, 0,
-                                                           IB_NODE_PORT_GUID_F);
-                               }
+       if (!query_node_info(&engine, from, NULL))
+               if (process_mads(&engine) != 0)
+                       goto error;
 
-                               if (get_remote_node(ibmad_port, fabric, node,
-                                                   port, path, i, dist) < 0)
-                                       goto error;
-                       }
-               }
-       }
+       fabric->total_mads_used = engine.total_smps;
 
        if (group_nodes(fabric))
                goto error;
 
-       return ((ibnd_fabric_t *) fabric);
+       smp_engine_destroy(&engine);
+       mad_rpc_close_port(scan.ibmad_port);
+       return fabric;
 error:
-       ibnd_destroy_fabric((ibnd_fabric_t *) fabric);
-       return (NULL);
+       smp_engine_destroy(&engine);
+       mad_rpc_close_port(scan.ibmad_port);
+       ibnd_destroy_fabric(fabric);
+       return NULL;
 }
 
-static void destroy_node(ibnd_node_t * node)
+void destroy_node(ibnd_node_t * node)
 {
        int p = 0;
 
-       for (p = 0; p <= node->numports; p++) {
-               free(node->ports[p]);
+       if (node->ports) {
+               for (p = 0; p <= node->numports; p++)
+                       free(node->ports[p]);
+               free(node->ports);
        }
-       free(node->ports);
        free(node);
 }
 
 void ibnd_destroy_fabric(ibnd_fabric_t * fabric)
 {
-       int dist = 0;
        ibnd_node_t *node = NULL;
        ibnd_node_t *next = NULL;
        ibnd_chassis_t *ch, *ch_next;
@@ -685,41 +556,21 @@ void ibnd_destroy_fabric(ibnd_fabric_t * fabric)
        if (!fabric)
                return;
 
-       ch = fabric->first_chassis;
+       ch = fabric->chassis;
        while (ch) {
                ch_next = ch->next;
                free(ch);
                ch = ch_next;
        }
-       for (dist = 0; dist <= MAXHOPS; dist++) {
-               node = fabric->nodesdist[dist];
-               while (node) {
-                       next = node->dnext;
-                       destroy_node(node);
-                       node = next;
-               }
+       node = fabric->nodes;
+       while (node) {
+               next = node->next;
+               destroy_node(node);
+               node = next;
        }
        free(fabric);
 }
 
-void ibnd_debug(int i)
-{
-       if (i) {
-               ibdebug++;
-               madrpc_show_errors(1);
-               umad_debug(i);
-       } else {
-               ibdebug = 0;
-               madrpc_show_errors(0);
-               umad_debug(0);
-       }
-}
-
-void ibnd_show_progress(int i)
-{
-       show_progress = i;
-}
-
 void ibnd_iter_nodes(ibnd_fabric_t * fabric, ibnd_iter_node_func_t func,
                     void *user_data)
 {
@@ -735,9 +586,8 @@ void ibnd_iter_nodes(ibnd_fabric_t * fabric, ibnd_iter_node_func_t func,
                return;
        }
 
-       for (cur = fabric->nodes; cur; cur = cur->next) {
+       for (cur = fabric->nodes; cur; cur = cur->next)
                func(cur, user_data);
-       }
 }
 
 void ibnd_iter_nodes_type(ibnd_fabric_t * fabric, ibnd_iter_node_func_t func,
@@ -771,7 +621,6 @@ void ibnd_iter_nodes_type(ibnd_fabric_t * fabric, ibnd_iter_node_func_t func,
                break;
        }
 
-       for (cur = list; cur; cur = cur->type_next) {
-               func((ibnd_node_t *) cur, user_data);
-       }
+       for (cur = list; cur; cur = cur->type_next)
+               func(cur, user_data);
 }
diff --git a/trunk/ulp/libibnetdisc/src/ibnetdisc_cache.c b/trunk/ulp/libibnetdisc/src/ibnetdisc_cache.c
new file mode 100644 (file)
index 0000000..10b2a37
--- /dev/null
@@ -0,0 +1,942 @@
+/*
+ * Copyright (c) 2004-2007 Voltaire Inc.  All rights reserved.
+ * Copyright (c) 2007 Xsigo Systems Inc.  All rights reserved.
+ * Copyright (c) 2008 Lawrence Livermore National Laboratory
+ *
+ * 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 */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <inttypes.h>
+
+#include <infiniband/ibnetdisc.h>
+
+#include "internal.h"
+#include "chassis.h"
+
+/* For this caching lib, we always cache little endian */
+
+/* Cache format
+ *
+ * Bytes 1-4 - magic number
+ * Bytes 5-8 - version number
+ * Bytes 9-12 - node count
+ * Bytes 13-16 - port count
+ * Bytes 17-24 - "from node" guid
+ * Bytes 25-28 - maxhops discovered
+ * Bytes X-Y - nodes (variable length)
+ * Bytes X-Y - ports (variable length)
+ *
+ * Nodes are cached as
+ *
+ * 2 bytes - smalid
+ * 1 byte - smalmc
+ * 1 byte - smaenhsp0 flag
+ * IB_SMP_DATA_SIZE bytes - switchinfo
+ * 8 bytes - guid
+ * 1 byte - type
+ * 1 byte - numports
+ * IB_SMP_DATA_SIZE bytes - info
+ * IB_SMP_DATA_SIZE bytes - nodedesc
+ * 1 byte - number of ports stored
+ * 8 bytes - portguid A
+ * 1 byte - port num A
+ * 8 bytes - portguid B
+ * 1 byte - port num B
+ * ... etc., depending on number of ports stored
+ *
+ * Ports are cached as
+ *
+ * 8 bytes - guid
+ * 1 byte - portnum
+ * 1 byte - external portnum
+ * 2 bytes - base lid
+ * 1 byte - lmc
+ * IB_SMP_DATA_SIZE bytes - info
+ * 8 bytes - node guid port "owned" by
+ * 1 byte - flag indicating if remote port exists
+ * 8 bytes - port guid remotely connected to
+ * 1 byte - port num remotely connected to
+ */
+
+/* Structs that hold cache info temporarily before
+ * the real structs can be reconstructed.
+ */
+
+typedef struct ibnd_port_cache_key {
+       uint64_t guid;
+       uint8_t portnum;
+} ibnd_port_cache_key_t;
+
+typedef struct ibnd_node_cache {
+       ibnd_node_t *node;
+       uint8_t ports_stored_count;
+       ibnd_port_cache_key_t *port_cache_keys;
+       struct ibnd_node_cache *next;
+       struct ibnd_node_cache *htnext;
+       int node_stored_to_fabric;
+} ibnd_node_cache_t;
+
+typedef struct ibnd_port_cache {
+       ibnd_port_t *port;
+       uint64_t node_guid;
+       uint8_t remoteport_flag;
+       ibnd_port_cache_key_t remoteport_cache_key;
+       struct ibnd_port_cache *next;
+       struct ibnd_port_cache *htnext;
+       int port_stored_to_fabric;
+} ibnd_port_cache_t;
+
+typedef struct ibnd_fabric_cache {
+       ibnd_fabric_t *fabric;
+       uint64_t from_node_guid;
+       ibnd_node_cache_t *nodes_cache;
+       ibnd_port_cache_t *ports_cache;
+       ibnd_node_cache_t *nodescachetbl[HTSZ];
+       ibnd_port_cache_t *portscachetbl[HTSZ];
+} ibnd_fabric_cache_t;
+
+#define IBND_FABRIC_CACHE_BUFLEN  4096
+#define IBND_FABRIC_CACHE_MAGIC   0x8FE7832B
+#define IBND_FABRIC_CACHE_VERSION 0x00000001
+
+#define IBND_FABRIC_CACHE_COUNT_OFFSET 8
+
+#define IBND_FABRIC_CACHE_HEADER_LEN   (28)
+#define IBND_NODE_CACHE_HEADER_LEN     (15 + IB_SMP_DATA_SIZE*3)
+#define IBND_PORT_CACHE_KEY_LEN        (8 + 1)
+#define IBND_PORT_CACHE_LEN            (31 + IB_SMP_DATA_SIZE)
+
+static ssize_t ibnd_read(int fd, void *buf, size_t count)
+{
+       size_t count_done = 0;
+       ssize_t ret;
+
+       while ((count - count_done) > 0) {
+               ret = read(fd, ((char *) buf) + count_done, count - count_done);
+               if (ret < 0) {
+                       if (errno == EINTR)
+                               continue;
+                       else {
+                               IBND_DEBUG("read: %s\n", strerror(errno));
+                               return -1;
+                       }
+               }
+               if (!ret)
+                       break;
+               count_done += ret;
+       }
+
+       if (count_done != count) {
+               IBND_DEBUG("read: read short\n");
+               return -1;
+       }
+
+       return count_done;
+}
+
+static size_t _unmarshall8(uint8_t * inbuf, uint8_t * num)
+{
+       (*num) = inbuf[0];
+
+       return (sizeof(*num));
+}
+
+static size_t _unmarshall16(uint8_t * inbuf, uint16_t * num)
+{
+       (*num) = (uint64_t) inbuf[0];
+       (*num) |= ((uint16_t) inbuf[1] << 8);
+
+       return (sizeof(*num));
+}
+
+static size_t _unmarshall32(uint8_t * inbuf, uint32_t * num)
+{
+       (*num) = (uint32_t) inbuf[0];
+       (*num) |= ((uint32_t) inbuf[1] << 8);
+       (*num) |= ((uint32_t) inbuf[2] << 16);
+       (*num) |= ((uint32_t) inbuf[3] << 24);
+
+       return (sizeof(*num));
+}
+
+static size_t _unmarshall64(uint8_t * inbuf, uint64_t * num)
+{
+       (*num) = (uint64_t) inbuf[0];
+       (*num) |= ((uint64_t) inbuf[1] << 8);
+       (*num) |= ((uint64_t) inbuf[2] << 16);
+       (*num) |= ((uint64_t) inbuf[3] << 24);
+       (*num) |= ((uint64_t) inbuf[4] << 32);
+       (*num) |= ((uint64_t) inbuf[5] << 40);
+       (*num) |= ((uint64_t) inbuf[6] << 48);
+       (*num) |= ((uint64_t) inbuf[7] << 56);
+
+       return (sizeof(*num));
+}
+
+static size_t _unmarshall_buf(const void *inbuf, void *outbuf, unsigned int len)
+{
+       memcpy(outbuf, inbuf, len);
+
+       return len;
+}
+
+static int _load_header_info(int fd, ibnd_fabric_cache_t * fabric_cache,
+                            unsigned int *node_count, unsigned int *port_count)
+{
+       uint8_t buf[IBND_FABRIC_CACHE_BUFLEN];
+       uint32_t magic = 0;
+       uint32_t version = 0;
+       size_t offset = 0;
+       uint32_t tmp32;
+
+       if (ibnd_read(fd, buf, IBND_FABRIC_CACHE_HEADER_LEN) < 0)
+               return -1;
+
+       offset += _unmarshall32(buf + offset, &magic);
+
+       if (magic != IBND_FABRIC_CACHE_MAGIC) {
+               IBND_DEBUG("invalid fabric cache file\n");
+               return -1;
+       }
+
+       offset += _unmarshall32(buf + offset, &version);
+
+       if (version != IBND_FABRIC_CACHE_VERSION) {
+               IBND_DEBUG("invalid fabric cache version\n");
+               return -1;
+       }
+
+       offset += _unmarshall32(buf + offset, node_count);
+       offset += _unmarshall32(buf + offset, port_count);
+
+       offset += _unmarshall64(buf + offset, &fabric_cache->from_node_guid);
+       offset += _unmarshall32(buf + offset, &tmp32);
+       fabric_cache->fabric->maxhops_discovered = tmp32;
+
+       return 0;
+}
+
+static void _destroy_ibnd_node_cache(ibnd_node_cache_t * node_cache)
+{
+       free(node_cache->port_cache_keys);
+       if (!node_cache->node_stored_to_fabric && node_cache->node)
+               destroy_node(node_cache->node);
+       free(node_cache);
+}
+
+static void _destroy_ibnd_fabric_cache(ibnd_fabric_cache_t * fabric_cache)
+{
+       ibnd_node_cache_t *node_cache;
+       ibnd_node_cache_t *node_cache_next;
+       ibnd_port_cache_t *port_cache;
+       ibnd_port_cache_t *port_cache_next;
+
+       if (!fabric_cache)
+               return;
+
+       node_cache = fabric_cache->nodes_cache;
+       while (node_cache) {
+               node_cache_next = node_cache->next;
+
+               _destroy_ibnd_node_cache(node_cache);
+
+               node_cache = node_cache_next;
+       }
+
+       port_cache = fabric_cache->ports_cache;
+       while (port_cache) {
+               port_cache_next = port_cache->next;
+
+               if (!port_cache->port_stored_to_fabric && port_cache->port)
+                       free(port_cache->port);
+               free(port_cache);
+
+               port_cache = port_cache_next;
+       }
+
+       free(fabric_cache);
+}
+
+static void store_node_cache(ibnd_node_cache_t * node_cache,
+                            ibnd_fabric_cache_t * fabric_cache)
+{
+       int hash_indx = HASHGUID(node_cache->node->guid) % HTSZ;
+
+       node_cache->next = fabric_cache->nodes_cache;
+       fabric_cache->nodes_cache = node_cache;
+
+       node_cache->htnext = fabric_cache->nodescachetbl[hash_indx];
+       fabric_cache->nodescachetbl[hash_indx] = node_cache;
+}
+
+static int _load_node(int fd, ibnd_fabric_cache_t * fabric_cache)
+{
+       uint8_t buf[IBND_FABRIC_CACHE_BUFLEN];
+       ibnd_node_cache_t *node_cache = NULL;
+       ibnd_node_t *node = NULL;
+       size_t offset = 0;
+       uint8_t tmp8;
+
+       node_cache = (ibnd_node_cache_t *) malloc(sizeof(ibnd_node_cache_t));
+       if (!node_cache) {
+               IBND_DEBUG("OOM: node_cache\n");
+               return -1;
+       }
+       memset(node_cache, '\0', sizeof(ibnd_node_cache_t));
+
+       node = (ibnd_node_t *) malloc(sizeof(ibnd_node_t));
+       if (!node) {
+               IBND_DEBUG("OOM: node\n");
+               return -1;
+       }
+       memset(node, '\0', sizeof(ibnd_node_t));
+
+       node_cache->node = node;
+
+       if (ibnd_read(fd, buf, IBND_NODE_CACHE_HEADER_LEN) < 0)
+               goto cleanup;
+
+       offset += _unmarshall16(buf + offset, &node->smalid);
+       offset += _unmarshall8(buf + offset, &node->smalmc);
+       offset += _unmarshall8(buf + offset, &tmp8);
+       node->smaenhsp0 = tmp8;
+       offset += _unmarshall_buf(buf + offset, node->switchinfo,
+                                 IB_SMP_DATA_SIZE);
+       offset += _unmarshall64(buf + offset, &node->guid);
+       offset += _unmarshall8(buf + offset, &tmp8);
+       node->type = tmp8;
+       offset += _unmarshall8(buf + offset, &tmp8);
+       node->numports = tmp8;
+       offset += _unmarshall_buf(buf + offset, node->info, IB_SMP_DATA_SIZE);
+       offset += _unmarshall_buf(buf + offset, node->nodedesc,
+                                 IB_SMP_DATA_SIZE);
+
+       offset += _unmarshall8(buf + offset, &node_cache->ports_stored_count);
+
+       if (node_cache->ports_stored_count) {
+               unsigned int tomalloc = 0;
+               unsigned int toread = 0;
+               unsigned int i;
+
+               tomalloc =
+                   sizeof(ibnd_port_cache_key_t) *
+                   node_cache->ports_stored_count;
+
+               toread =
+                   IBND_PORT_CACHE_KEY_LEN * node_cache->ports_stored_count;
+
+               node_cache->port_cache_keys =
+                   (ibnd_port_cache_key_t *) malloc(tomalloc);
+               if (!node_cache->port_cache_keys) {
+                       IBND_DEBUG("OOM: node_cache port_cache_keys\n");
+                       goto cleanup;
+               }
+
+               if (ibnd_read(fd, buf, toread) < 0)
+                       goto cleanup;
+
+               offset = 0;
+
+               for (i = 0; i < node_cache->ports_stored_count; i++) {
+                       offset +=
+                           _unmarshall64(buf + offset,
+                                         &node_cache->port_cache_keys[i].guid);
+                       offset +=
+                           _unmarshall8(buf + offset,
+                                        &node_cache->
+                                        port_cache_keys[i].portnum);
+               }
+       }
+
+       store_node_cache(node_cache, fabric_cache);
+
+       return 0;
+
+cleanup:
+       _destroy_ibnd_node_cache(node_cache);
+       return -1;
+}
+
+static void store_port_cache(ibnd_port_cache_t * port_cache,
+                            ibnd_fabric_cache_t * fabric_cache)
+{
+       int hash_indx = HASHGUID(port_cache->port->guid) % HTSZ;
+
+       port_cache->next = fabric_cache->ports_cache;
+       fabric_cache->ports_cache = port_cache;
+
+       port_cache->htnext = fabric_cache->portscachetbl[hash_indx];
+       fabric_cache->portscachetbl[hash_indx] = port_cache;
+}
+
+static int _load_port(int fd, ibnd_fabric_cache_t * fabric_cache)
+{
+       uint8_t buf[IBND_FABRIC_CACHE_BUFLEN];
+       ibnd_port_cache_t *port_cache = NULL;
+       ibnd_port_t *port = NULL;
+       size_t offset = 0;
+       uint8_t tmp8;
+
+       port_cache = (ibnd_port_cache_t *) malloc(sizeof(ibnd_port_cache_t));
+       if (!port_cache) {
+               IBND_DEBUG("OOM: port_cache\n");
+               return -1;
+       }
+       memset(port_cache, '\0', sizeof(ibnd_port_cache_t));
+
+       port = (ibnd_port_t *) malloc(sizeof(ibnd_port_t));
+       if (!port) {
+               IBND_DEBUG("OOM: port\n");
+               return -1;
+       }
+       memset(port, '\0', sizeof(ibnd_port_t));
+
+       port_cache->port = port;
+
+       if (ibnd_read(fd, buf, IBND_PORT_CACHE_LEN) < 0)
+               goto cleanup;
+
+       offset += _unmarshall64(buf + offset, &port->guid);
+       offset += _unmarshall8(buf + offset, &tmp8);
+       port->portnum = tmp8;
+       offset += _unmarshall8(buf + offset, &tmp8);
+       port->ext_portnum = tmp8;
+       offset += _unmarshall16(buf + offset, &port->base_lid);
+       offset += _unmarshall8(buf + offset, &port->lmc);
+       offset += _unmarshall_buf(buf + offset, port->info, IB_SMP_DATA_SIZE);
+       offset += _unmarshall64(buf + offset, &port_cache->node_guid);
+       offset += _unmarshall8(buf + offset, &port_cache->remoteport_flag);
+       offset +=
+           _unmarshall64(buf + offset, &port_cache->remoteport_cache_key.guid);
+       offset +=
+           _unmarshall8(buf + offset,
+                        &port_cache->remoteport_cache_key.portnum);
+
+       store_port_cache(port_cache, fabric_cache);
+
+       return 0;
+
+cleanup:
+       free(port);
+       free(port_cache);
+       return -1;
+}
+
+static ibnd_port_cache_t *_find_port(ibnd_fabric_cache_t * fabric_cache,
+                                    ibnd_port_cache_key_t * port_cache_key)
+{
+       int hash_indx = HASHGUID(port_cache_key->guid) % HTSZ;
+       ibnd_port_cache_t *port_cache;
+
+       for (port_cache = fabric_cache->portscachetbl[hash_indx];
+            port_cache; port_cache = port_cache->htnext) {
+               if (port_cache->port->guid == port_cache_key->guid
+                   && port_cache->port->portnum == port_cache_key->portnum)
+                       return port_cache;
+       }
+
+       return NULL;
+}
+
+static ibnd_node_cache_t *_find_node(ibnd_fabric_cache_t * fabric_cache,
+                                    uint64_t guid)
+{
+       int hash_indx = HASHGUID(guid) % HTSZ;
+       ibnd_node_cache_t *node_cache;
+
+       for (node_cache = fabric_cache->nodescachetbl[hash_indx];
+            node_cache; node_cache = node_cache->htnext) {
+               if (node_cache->node->guid == guid)
+                       return node_cache;
+       }
+
+       return NULL;
+}
+
+static int _fill_port(ibnd_fabric_cache_t * fabric_cache, ibnd_node_t * node,
+                     ibnd_port_cache_key_t * port_cache_key)
+{
+       ibnd_port_cache_t *port_cache;
+
+       if (!(port_cache = _find_port(fabric_cache, port_cache_key))) {
+               IBND_DEBUG("Cache invalid: cannot find port\n");
+               return -1;
+       }
+
+       if (port_cache->port_stored_to_fabric) {
+               IBND_DEBUG("Cache invalid: duplicate port discovered\n");
+               return -1;
+       }
+
+       node->ports[port_cache->port->portnum] = port_cache->port;
+       port_cache->port_stored_to_fabric++;
+
+       /* achu: needed if user wishes to re-cache a loaded fabric.
+        * Otherwise, mostly unnecessary to do this.
+        */
+       add_to_portguid_hash(port_cache->port, fabric_cache->fabric->portstbl);
+       return 0;
+}
+
+static int _rebuild_nodes(ibnd_fabric_cache_t * fabric_cache)
+{
+       ibnd_node_cache_t *node_cache;
+       ibnd_node_cache_t *node_cache_next;
+
+       node_cache = fabric_cache->nodes_cache;
+       while (node_cache) {
+               ibnd_node_t *node;
+               int i;
+
+               node_cache_next = node_cache->next;
+
+               node = node_cache->node;
+
+               /* Insert node into appropriate data structures */
+
+               node->next = fabric_cache->fabric->nodes;
+               fabric_cache->fabric->nodes = node;
+
+               add_to_nodeguid_hash(node_cache->node,
+                                    fabric_cache->fabric->nodestbl);
+
+               add_to_type_list(node_cache->node, fabric_cache->fabric);
+
+               node_cache->node_stored_to_fabric++;
+
+               /* Rebuild node ports array */
+
+               if (!(node->ports =
+                     calloc(sizeof(*node->ports), node->numports + 1))) {
+                       IBND_DEBUG("OOM: node->ports\n");
+                       return -1;
+               }
+
+               for (i = 0; i < node_cache->ports_stored_count; i++) {
+                       if (_fill_port(fabric_cache, node,
+                                      &node_cache->port_cache_keys[i]) < 0)
+                               return -1;
+               }
+
+               node_cache = node_cache_next;
+       }
+
+       return 0;
+}
+
+static int _rebuild_ports(ibnd_fabric_cache_t * fabric_cache)
+{
+       ibnd_port_cache_t *port_cache;
+       ibnd_port_cache_t *port_cache_next;
+
+       port_cache = fabric_cache->ports_cache;
+       while (port_cache) {
+               ibnd_node_cache_t *node_cache;
+               ibnd_port_cache_t *remoteport_cache;
+               ibnd_port_t *port;
+
+               port_cache_next = port_cache->next;
+
+               port = port_cache->port;
+
+               if (!(node_cache =
+                     _find_node(fabric_cache, port_cache->node_guid))) {
+                       IBND_DEBUG("Cache invalid: cannot find node\n");
+                       return -1;
+               }
+
+               port->node = node_cache->node;
+
+               if (port_cache->remoteport_flag) {
+                       if (!(remoteport_cache = _find_port(fabric_cache,
+                                                           &port_cache->remoteport_cache_key)))
+                       {
+                               IBND_DEBUG
+                                   ("Cache invalid: cannot find remote port\n");
+                               return -1;
+                       }
+
+                       port->remoteport = remoteport_cache->port;
+               } else
+                       port->remoteport = NULL;
+
+               port_cache = port_cache_next;
+       }
+
+       return 0;
+}
+
+ibnd_fabric_t *ibnd_load_fabric(const char *file, unsigned int flags)
+{
+       unsigned int node_count = 0;
+       unsigned int port_count = 0;
+       ibnd_fabric_cache_t *fabric_cache = NULL;
+       ibnd_fabric_t *fabric = NULL;
+       ibnd_node_cache_t *node_cache = NULL;
+       int fd = -1;
+       unsigned int i;
+
+       if (!file) {
+               IBND_DEBUG("file parameter NULL\n");
+               return NULL;
+       }
+
+       if ((fd = open(file, O_RDONLY)) < 0) {
+               IBND_DEBUG("open: %s\n", strerror(errno));
+               return NULL;
+       }
+
+       fabric_cache =
+           (ibnd_fabric_cache_t *) malloc(sizeof(ibnd_fabric_cache_t));
+       if (!fabric_cache) {
+               IBND_DEBUG("OOM: fabric_cache\n");
+               goto cleanup;
+       }
+       memset(fabric_cache, '\0', sizeof(ibnd_fabric_cache_t));
+
+       fabric = (ibnd_fabric_t *) malloc(sizeof(ibnd_fabric_t));
+       if (!fabric) {
+               IBND_DEBUG("OOM: fabric\n");
+               goto cleanup;
+       }
+       memset(fabric, '\0', sizeof(ibnd_fabric_t));
+
+       fabric_cache->fabric = fabric;
+
+       if (_load_header_info(fd, fabric_cache, &node_count, &port_count) < 0)
+               goto cleanup;
+
+       for (i = 0; i < node_count; i++) {
+               if (_load_node(fd, fabric_cache) < 0)
+                       goto cleanup;
+       }
+
+       for (i = 0; i < port_count; i++) {
+               if (_load_port(fd, fabric_cache) < 0)
+                       goto cleanup;
+       }
+
+       /* Special case - find from node */
+       if (!(node_cache =
+             _find_node(fabric_cache, fabric_cache->from_node_guid))) {
+               IBND_DEBUG("Cache invalid: cannot find from node\n");
+               goto cleanup;
+       }
+       fabric->from_node = node_cache->node;
+
+       if (_rebuild_nodes(fabric_cache) < 0)
+               goto cleanup;
+
+       if (_rebuild_ports(fabric_cache) < 0)
+               goto cleanup;
+
+       if (group_nodes(fabric))
+               goto cleanup;
+
+       _destroy_ibnd_fabric_cache(fabric_cache);
+       close(fd);
+       return fabric;
+
+cleanup:
+       ibnd_destroy_fabric(fabric);
+       _destroy_ibnd_fabric_cache(fabric_cache);
+       close(fd);
+       return NULL;
+}
+
+static ssize_t ibnd_write(int fd, const void *buf, size_t count)
+{
+       size_t count_done = 0;
+       ssize_t ret;
+
+       while ((count - count_done) > 0) {
+               ret = write(fd, ((char *) buf) + count_done, count - count_done);
+               if (ret < 0) {
+                       if (errno == EINTR)
+                               continue;
+                       else {
+                               IBND_DEBUG("write: %s\n", strerror(errno));
+                               return -1;
+                       }
+               }
+               count_done += ret;
+       }
+       return count_done;
+}
+
+static size_t _marshall8(uint8_t * outbuf, uint8_t num)
+{
+       outbuf[0] = num;
+
+       return (sizeof(num));
+}
+
+static size_t _marshall16(uint8_t * outbuf, uint16_t num)
+{
+       outbuf[0] = num & 0x00FF;
+       outbuf[1] = (num & 0xFF00) >> 8;
+
+       return (sizeof(num));
+}
+
+static size_t _marshall32(uint8_t * outbuf, uint32_t num)
+{
+       outbuf[0] = num & 0x000000FF;
+       outbuf[1] = (num & 0x0000FF00) >> 8;
+       outbuf[2] = (num & 0x00FF0000) >> 16;
+       outbuf[3] = (num & 0xFF000000) >> 24;
+
+       return (sizeof(num));
+}
+
+static size_t _marshall64(uint8_t * outbuf, uint64_t num)
+{
+       outbuf[0] = (uint8_t) num;
+       outbuf[1] = (uint8_t) (num >> 8);
+       outbuf[2] = (uint8_t) (num >> 16);
+       outbuf[3] = (uint8_t) (num >> 24);
+       outbuf[4] = (uint8_t) (num >> 32);
+       outbuf[5] = (uint8_t) (num >> 40);
+       outbuf[6] = (uint8_t) (num >> 48);
+       outbuf[7] = (uint8_t) (num >> 56);
+
+       return (sizeof(num));
+}
+
+static size_t _marshall_buf(void *outbuf, const void *inbuf, unsigned int len)
+{
+       memcpy(outbuf, inbuf, len);
+
+       return len;
+}
+
+static int _cache_header_info(int fd, ibnd_fabric_t * fabric)
+{
+       uint8_t buf[IBND_FABRIC_CACHE_BUFLEN];
+       size_t offset = 0;
+
+       /* Store magic number, version, and other important info */
+       /* For this caching lib, we always assume cached as little endian */
+
+       offset += _marshall32(buf + offset, IBND_FABRIC_CACHE_MAGIC);
+       offset += _marshall32(buf + offset, IBND_FABRIC_CACHE_VERSION);
+       /* save space for node count */
+       offset += _marshall32(buf + offset, 0);
+       /* save space for port count */
+       offset += _marshall32(buf + offset, 0);
+       offset += _marshall64(buf + offset, fabric->from_node->guid);
+       offset += _marshall32(buf + offset, fabric->maxhops_discovered);
+
+       if (ibnd_write(fd, buf, offset) < 0)
+               return -1;
+
+       return 0;
+}
+
+static int _cache_header_counts(int fd, unsigned int node_count,
+                               unsigned int port_count)
+{
+       uint8_t buf[IBND_FABRIC_CACHE_BUFLEN];
+       size_t offset = 0;
+
+       offset += _marshall32(buf + offset, node_count);
+       offset += _marshall32(buf + offset, port_count);
+
+       if (lseek(fd, IBND_FABRIC_CACHE_COUNT_OFFSET, SEEK_SET) < 0) {
+               IBND_DEBUG("lseek: %s\n", strerror(errno));
+               return -1;
+       }
+
+       if (ibnd_write(fd, buf, offset) < 0)
+               return -1;
+
+       return 0;
+}
+
+static int _cache_node(int fd, ibnd_node_t * node)
+{
+       uint8_t buf[IBND_FABRIC_CACHE_BUFLEN];
+       size_t offset = 0;
+       size_t ports_stored_offset = 0;
+       uint8_t ports_stored_count = 0;
+       int i;
+
+       offset += _marshall16(buf + offset, node->smalid);
+       offset += _marshall8(buf + offset, node->smalmc);
+       offset += _marshall8(buf + offset, (uint8_t) node->smaenhsp0);
+       offset += _marshall_buf(buf + offset, node->switchinfo,
+                               IB_SMP_DATA_SIZE);
+       offset += _marshall64(buf + offset, node->guid);
+       offset += _marshall8(buf + offset, (uint8_t) node->type);
+       offset += _marshall8(buf + offset, (uint8_t) node->numports);
+       offset += _marshall_buf(buf + offset, node->info, IB_SMP_DATA_SIZE);
+       offset += _marshall_buf(buf + offset, node->nodedesc, IB_SMP_DATA_SIZE);
+       /* need to come back later and store number of stored ports
+        * because port entries can be NULL or (in the case of switches)
+        * there is an additional port 0 not accounted for in numports.
+        */
+       ports_stored_offset = offset;
+       offset += sizeof(uint8_t);
+
+       for (i = 0; i <= node->numports; i++) {
+               if (node->ports[i]) {
+                       offset += _marshall64(buf + offset,
+                                             node->ports[i]->guid);
+                       offset += _marshall8(buf + offset,
+                                            (uint8_t) node->ports[i]->portnum);
+                       ports_stored_count++;
+               }
+       }
+
+       /* go back and store number of port keys stored */
+       _marshall8(buf + ports_stored_offset, ports_stored_count);
+
+       if (ibnd_write(fd, buf, offset) < 0)
+               return -1;
+
+       return 0;
+}
+
+static int _cache_port(int fd, ibnd_port_t * port)
+{
+       uint8_t buf[IBND_FABRIC_CACHE_BUFLEN];
+       size_t offset = 0;
+
+       offset += _marshall64(buf + offset, port->guid);
+       offset += _marshall8(buf + offset, (uint8_t) port->portnum);
+       offset += _marshall8(buf + offset, (uint8_t) port->ext_portnum);
+       offset += _marshall16(buf + offset, port->base_lid);
+       offset += _marshall8(buf + offset, port->lmc);
+       offset += _marshall_buf(buf + offset, port->info, IB_SMP_DATA_SIZE);
+       offset += _marshall64(buf + offset, port->node->guid);
+       if (port->remoteport) {
+               offset += _marshall8(buf + offset, 1);
+               offset += _marshall64(buf + offset, port->remoteport->guid);
+               offset += _marshall8(buf + offset, (uint8_t) port->remoteport->portnum);
+       } else {
+               offset += _marshall8(buf + offset, 0);
+               offset += _marshall64(buf + offset, 0);
+               offset += _marshall8(buf + offset, 0);
+       }
+
+       if (ibnd_write(fd, buf, offset) < 0)
+               return -1;
+
+       return 0;
+}
+
+int ibnd_cache_fabric(ibnd_fabric_t * fabric, const char *file,
+                     unsigned int flags)
+{
+       struct stat statbuf;
+       ibnd_node_t *node = NULL;
+       ibnd_node_t *node_next = NULL;
+       unsigned int node_count = 0;
+       ibnd_port_t *port = NULL;
+       ibnd_port_t *port_next = NULL;
+       unsigned int port_count = 0;
+       int fd;
+       int i;
+
+       if (!fabric) {
+               IBND_DEBUG("fabric parameter NULL\n");
+               return -1;
+       }
+
+       if (!file) {
+               IBND_DEBUG("file parameter NULL\n");
+               return -1;
+       }
+
+       if (!stat(file, &statbuf)) {
+               IBND_DEBUG("file '%s' already exists\n", file);
+               return -1;
+       }
+
+       if ((fd = open(file, O_CREAT | O_EXCL | O_WRONLY, 0644)) < 0) {
+               IBND_DEBUG("open: %s\n", strerror(errno));
+               return -1;
+       }
+
+       if (_cache_header_info(fd, fabric) < 0)
+               goto cleanup;
+
+       node = fabric->nodes;
+       while (node) {
+               node_next = node->next;
+
+               if (_cache_node(fd, node) < 0)
+                       goto cleanup;
+
+               node_count++;
+               node = node_next;
+       }
+
+       for (i = 0; i < HTSZ; i++) {
+               port = fabric->portstbl[i];
+               while (port) {
+                       port_next = port->htnext;
+
+                       if (_cache_port(fd, port) < 0)
+                               goto cleanup;
+
+                       port_count++;
+                       port = port_next;
+               }
+       }
+
+       if (_cache_header_counts(fd, node_count, port_count) < 0)
+               goto cleanup;
+
+       if (close(fd) < 0) {
+               IBND_DEBUG("close: %s\n", strerror(errno));
+               goto cleanup;
+       }
+
+       return 0;
+
+cleanup:
+       unlink(file);
+       close(fd);
+       return -1;
+}
index 64c4085107ceba0f20f0e579ef53aeec689ddb57..0ac15b98c1f020156970778cb7b5f3f7d13c523d 100644 (file)
@@ -6,12 +6,9 @@ LIBRARY libibnetdisc.dll
 \r
 #ifndef _WIN64\r
 EXPORTS\r
-               ibnd_debug;\r
-               ibnd_show_progress;\r
                ibnd_discover_fabric;\r
                ibnd_destroy_fabric;\r
                ibnd_find_node_guid;\r
-               ibnd_update_node;\r
                ibnd_find_node_dr;\r
                ibnd_is_xsigo_guid;\r
                ibnd_is_xsigo_tca;\r
index 21ff476d4ac63cdc1f21ae45435117a03ea501c6..3c599ecff543a57ca5a2e5bf012918f50d09f206 100644 (file)
@@ -39,6 +39,7 @@
 #define _INTERNAL_H_
 
 #include <infiniband/ibnetdisc.h>
+#include <complib/cl_qmap.h>
 
 #define        IBND_DEBUG(fmt, ...) \
        if (ibdebug) { \
 /* HASH table defines */
 #define HASHGUID(guid) ((uint32_t)(((uint32_t)(guid) * 101) ^ ((uint32_t)((guid) >> 32) * 103)))
 
+#define MAXHOPS         63
+
+#define DEFAULT_MAX_SMP_ON_WIRE 2
+#define DEFAULT_TIMEOUT 1000
+#define DEFAULT_RETRIES 3
+
+typedef struct ibnd_scan {
+       ib_portid_t selfportid;
+       ibnd_fabric_t *fabric;
+       struct ibnd_config *cfg;
+       struct ibmad_port *ibmad_port;
+} ibnd_scan_t;
+
+typedef struct ibnd_smp ibnd_smp_t;
+typedef struct smp_engine smp_engine_t;
+typedef int (*smp_comp_cb_t) (smp_engine_t * engine, ibnd_smp_t * smp,
+                             uint8_t * mad_resp, void *cb_data);
+struct ibnd_smp {
+       cl_map_item_t on_wire;
+       struct ibnd_smp *qnext;
+       smp_comp_cb_t cb;
+       void *cb_data;
+       ib_portid_t path;
+       ib_rpc_t rpc;
+};
+
+struct smp_engine {
+       int umad_fd;
+       int smi_agent;
+       int smi_dir_agent;
+       ibnd_smp_t *smp_queue_head;
+       ibnd_smp_t *smp_queue_tail;
+       void *user_data;
+       cl_qmap_t smps_on_wire;
+       struct ibnd_config *cfg;
+       unsigned total_smps;
+};
+
+int smp_engine_init(smp_engine_t * engine, char * ca_name, int ca_port,
+                   void *user_data, ibnd_config_t *cfg);
+int issue_smp(smp_engine_t * engine, ib_portid_t * portid,
+             unsigned attrid, unsigned mod, smp_comp_cb_t cb, void *cb_data);
+int process_mads(smp_engine_t * engine);
+void smp_engine_destroy(smp_engine_t * engine);
+
+void add_to_nodeguid_hash(ibnd_node_t * node, ibnd_node_t * hash[]);
+
+void add_to_portguid_hash(ibnd_port_t * port, ibnd_port_t * hash[]);
+
+void add_to_type_list(ibnd_node_t * node, ibnd_fabric_t * fabric);
+
+void destroy_node(ibnd_node_t * node);
+
 #endif                         /* _INTERNAL_H_ */
diff --git a/trunk/ulp/libibnetdisc/src/query_smp.c b/trunk/ulp/libibnetdisc/src/query_smp.c
new file mode 100644 (file)
index 0000000..5fb3e18
--- /dev/null
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 2010 Lawrence Livermore National Laboratory
+ *
+ * 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 <errno.h>
+#include <infiniband/ibnetdisc.h>
+#include <infiniband/umad.h>
+#include "internal.h"
+
+static void queue_smp(smp_engine_t * engine, ibnd_smp_t * smp)
+{
+       smp->qnext = NULL;
+       if (!engine->smp_queue_head) {
+               engine->smp_queue_head = smp;
+               engine->smp_queue_tail = smp;
+       } else {
+               engine->smp_queue_tail->qnext = smp;
+               engine->smp_queue_tail = smp;
+       }
+}
+
+static ibnd_smp_t *get_smp(smp_engine_t * engine)
+{
+       ibnd_smp_t *head = engine->smp_queue_head;
+       ibnd_smp_t *tail = engine->smp_queue_tail;
+       ibnd_smp_t *rc = head;
+       if (head) {
+               if (tail == head)
+                       engine->smp_queue_tail = NULL;
+               engine->smp_queue_head = head->qnext;
+       }
+       return rc;
+}
+
+static int send_smp(ibnd_smp_t * smp, smp_engine_t * engine)
+{
+       int rc = 0;
+       uint8_t umad[1024];
+       ib_rpc_t *rpc = &smp->rpc;
+       int agent = 0;
+
+       memset(umad, 0, umad_size() + IB_MAD_SIZE);
+
+       if (rpc->mgtclass == IB_SMI_CLASS) {
+               agent = engine->smi_agent;
+       } else if (rpc->mgtclass == IB_SMI_DIRECT_CLASS) {
+               agent = engine->smi_dir_agent;
+       } else {
+               IBND_ERROR("Invalid class for RPC\n");
+               return (-EIO);
+       }
+
+       if ((rc = mad_build_pkt(umad, &smp->rpc, &smp->path, NULL, NULL))
+           < 0) {
+               IBND_ERROR("mad_build_pkt failed; %d\n", rc);
+               return rc;
+       }
+
+       if ((rc = umad_send(engine->umad_fd, agent, umad, IB_MAD_SIZE,
+                           engine->cfg->timeout_ms, engine->cfg->retries)) < 0) {
+               IBND_ERROR("send failed; %d\n", rc);
+               return rc;
+       }
+
+       return 0;
+}
+
+static int process_smp_queue(smp_engine_t * engine)
+{
+       int rc = 0;
+       ibnd_smp_t *smp;
+       while (cl_qmap_count(&engine->smps_on_wire)
+              < engine->cfg->max_smps) {
+               smp = get_smp(engine);
+               if (!smp)
+                       return 0;
+
+               if ((rc = send_smp(smp, engine)) != 0) {
+                       free(smp);
+                       return rc;
+               }
+               cl_qmap_insert(&engine->smps_on_wire, (uint32_t) smp->rpc.trid,
+                              (cl_map_item_t *) smp);
+               engine->total_smps++;
+       }
+       return 0;
+}
+
+int issue_smp(smp_engine_t * engine, ib_portid_t * portid,
+             unsigned attrid, unsigned mod, smp_comp_cb_t cb, void *cb_data)
+{
+       ibnd_smp_t *smp = calloc(1, sizeof *smp);
+       if (!smp) {
+               IBND_ERROR("OOM\n");
+               return -ENOMEM;
+       }
+
+       smp->cb = cb;
+       smp->cb_data = cb_data;
+       smp->path = *portid;
+       smp->rpc.method = IB_MAD_METHOD_GET;
+       smp->rpc.attr.id = attrid;
+       smp->rpc.attr.mod = mod;
+       smp->rpc.timeout = engine->cfg->timeout_ms;
+       smp->rpc.datasz = IB_SMP_DATA_SIZE;
+       smp->rpc.dataoffs = IB_SMP_DATA_OFFS;
+       smp->rpc.trid = mad_trid();
+
+       if (portid->lid <= 0 || portid->drpath.drslid == 0xffff ||
+           portid->drpath.drdlid == 0xffff)
+               smp->rpc.mgtclass = IB_SMI_DIRECT_CLASS;        /* direct SMI */
+       else
+               smp->rpc.mgtclass = IB_SMI_CLASS;       /* Lid routed SMI */
+
+       portid->sl = 0;
+       portid->qp = 0;
+
+       queue_smp(engine, smp);
+       return process_smp_queue(engine);
+}
+
+static int process_one_recv(smp_engine_t * engine)
+{
+       int rc = 0;
+       int status = 0;
+       ibnd_smp_t *smp;
+       uint8_t *mad;
+       uint32_t trid;
+       uint8_t umad[sizeof(struct ib_user_mad) + IB_MAD_SIZE];
+       int length = umad_size() + IB_MAD_SIZE;
+
+       memset(umad, 0, sizeof(umad));
+
+       /* wait for the next message */
+       if ((rc = umad_recv(engine->umad_fd, umad, &length,
+                           0)) < 0) {
+               if (rc == -EWOULDBLOCK)
+                       return 0;
+               IBND_ERROR("umad_recv failed: %d\n", rc);
+               return -1;
+       }
+
+       mad = umad_get_mad(umad);
+       trid = (uint32_t) mad_get_field64(mad, 0, IB_MAD_TRID_F);
+
+       smp = (ibnd_smp_t *) cl_qmap_remove(&engine->smps_on_wire, trid);
+       if ((cl_map_item_t *) smp == cl_qmap_end(&engine->smps_on_wire)) {
+               IBND_ERROR("Failed to find matching smp for trid (%x)\n", trid);
+               return -1;
+       }
+
+       rc = process_smp_queue(engine);
+       if (rc)
+               goto error;
+
+       if ((status = umad_status(umad))) {
+               IBND_ERROR("umad (%s Attr 0x%x:%u) bad status %d; %s\n",
+                          portid2str(&smp->path), smp->rpc.attr.id,
+                          smp->rpc.attr.mod, status, strerror(status));
+       } else if ((status = mad_get_field(mad, 0, IB_DRSMP_STATUS_F))) {
+               IBND_ERROR("mad (%s Attr 0x%x:%u) bad status 0x%x\n",
+                          portid2str(&smp->path), smp->rpc.attr.id,
+                          smp->rpc.attr.mod, status);
+       } else
+               rc = smp->cb(engine, smp, mad, smp->cb_data);
+
+error:
+       free(smp);
+       return rc;
+}
+
+int smp_engine_init(smp_engine_t * engine, char * ca_name, int ca_port,
+                   void *user_data, ibnd_config_t *cfg)
+{
+       memset(engine, 0, sizeof(*engine));
+
+       if (umad_init() < 0) {
+               IBND_ERROR("umad_init failed\n");
+               return -EIO;
+       }
+
+       engine->umad_fd = umad_open_port(ca_name, ca_port);
+       if (engine->umad_fd < 0) {
+               IBND_ERROR("can't open UMAD port (%s:%d)\n", ca_name, ca_port);
+               return -EIO;
+       }
+
+       if ((engine->smi_agent = umad_register(engine->umad_fd,
+            IB_SMI_CLASS, 1, 0, 0)) < 0) {
+               IBND_ERROR("Failed to register SMI agent on (%s:%d)\n",
+                          ca_name, ca_port);
+               goto eio_close;
+       }
+
+       if ((engine->smi_dir_agent = umad_register(engine->umad_fd,
+            IB_SMI_DIRECT_CLASS, 1, 0, 0)) < 0) {
+               IBND_ERROR("Failed to register SMI_DIRECT agent on (%s:%d)\n",
+                          ca_name, ca_port);
+               goto eio_close;
+       }
+
+       engine->user_data = user_data;
+       cl_qmap_init(&engine->smps_on_wire);
+       engine->cfg = cfg;
+       return (0);
+
+eio_close:
+       umad_close_port(engine->umad_fd);
+       return (-EIO);
+}
+
+void smp_engine_destroy(smp_engine_t * engine)
+{
+       cl_map_item_t *item;
+       ibnd_smp_t *smp;
+
+       /* remove queued smps */
+       smp = get_smp(engine);
+       if (smp)
+               IBND_ERROR("outstanding SMP's\n");
+       for ( /* */ ; smp; smp = get_smp(engine))
+               free(smp);
+
+       /* remove smps from the wire queue */
+       item = cl_qmap_head(&engine->smps_on_wire);
+       if (item != cl_qmap_end(&engine->smps_on_wire))
+               IBND_ERROR("outstanding SMP's on wire\n");
+       for ( /* */ ; item != cl_qmap_end(&engine->smps_on_wire);
+            item = cl_qmap_head(&engine->smps_on_wire)) {
+               cl_qmap_remove_item(&engine->smps_on_wire, item);
+               free(item);
+       }
+
+       umad_close_port(engine->umad_fd);
+}
+
+int process_mads(smp_engine_t * engine)
+{
+       int rc;
+       while (!cl_is_qmap_empty(&engine->smps_on_wire))
+               if ((rc = process_one_recv(engine)) != 0)
+                       return rc;
+       return 0;
+}
index 53aa84b2031e32e32c9e6c65f5b2acee06896c92..ed0f3f390e0a184a617e50fd2b13bd8a52b04990 100644 (file)
@@ -1062,9 +1062,7 @@ void osm_dump_path_record(IN osm_log_t * p_log, IN const ib_path_rec_t * p_pr,
        if (osm_log_is_active(p_log, log_level)) {\r
                char gid_str[INET6_ADDRSTRLEN];\r
                char gid_str2[INET6_ADDRSTRLEN];\r
-#ifdef __WIN__\r
-               uint8_t *p_resv = (uint8_t*) &p_pr->resv1;\r
-#endif\r
+\r
                osm_log(p_log, log_level,\r
                        "PathRecord dump:\n"\r
                        "\t\t\t\tservice_id..............0x%016" PRIx64 "\n"\r
@@ -1093,13 +1091,8 @@ void osm_dump_path_record(IN osm_log_t * p_log, IN const ib_path_rec_t * p_pr,
                        p_pr->num_path, cl_ntoh16(p_pr->pkey),\r
                        ib_path_rec_qos_class(p_pr), ib_path_rec_sl(p_pr),\r
                        p_pr->mtu, p_pr->rate, p_pr->pkt_life, p_pr->preference,\r
-#ifdef __WIN__\r
-                       p_resv[0], p_resv[1], p_resv[2],\r
-                       p_resv[3], p_resv[4], p_resv[5]);\r
-#else\r
                        p_pr->resv2[0], p_pr->resv2[1], p_pr->resv2[2],\r
                        p_pr->resv2[3], p_pr->resv2[4], p_pr->resv2[5]);\r
-#endif\r
        }\r
 }\r
 \r
index 03271b4ebffca92e64e4b145b33b92e7b439c35c..7bfcdd4cbb688c43e5310507ad71243156a8ff24 100644 (file)
@@ -532,18 +532,6 @@ __srp_path_rec_equal(
 \r
 #if defined( _DEBUG_ )\r
 \r
-       if ( p_path_rec_1->resv1 != p_path_rec_2->resv1 )\r
-       {\r
-               SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
-                       ("resv1 does not match.\n") );\r
-       }\r
-\r
-       if ( p_path_rec_1->resv2 != p_path_rec_2->resv2 )\r
-       {\r
-               SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r
-                       ("resv2 does not match.\n") );\r
-       }\r
-\r
        if ( cl_memcmp( p_path_rec_1, p_path_rec_2, sizeof( ib_path_rec_t ) ) != 0 )\r
        {\r
                SRP_PRINT( TRACE_LEVEL_INFORMATION, SRP_DBG_DEBUG,\r