]> git.openfabrics.org - ~shefty/rdma-win.git/commitdiff
ib-diags: initial port of IB diagnostic tools
authorshefty <shefty@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Thu, 15 Jan 2009 07:24:33 +0000 (07:24 +0000)
committershefty <shefty@ad392aa1-c5ef-ae45-8dd8-e69d62a5ef86>
Thu, 15 Jan 2009 07:24:33 +0000 (07:24 +0000)
Only select tools ported yet.  Changes have not yet been merged into main git tree.

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

33 files changed:
branches/winverbs/tools/infiniband_diags/dirs [new file with mode: 0644]
branches/winverbs/tools/infiniband_diags/include/grouping.h [new file with mode: 0644]
branches/winverbs/tools/infiniband_diags/include/ibdiag_common.h [new file with mode: 0644]
branches/winverbs/tools/infiniband_diags/include/ibdiag_version.h [new file with mode: 0644]
branches/winverbs/tools/infiniband_diags/include/ibdiag_version.h.in [new file with mode: 0644]
branches/winverbs/tools/infiniband_diags/include/ibnetdiscover.h [new file with mode: 0644]
branches/winverbs/tools/infiniband_diags/src/dirs [new file with mode: 0644]
branches/winverbs/tools/infiniband_diags/src/grouping.c [new file with mode: 0644]
branches/winverbs/tools/infiniband_diags/src/ibaddr.c [new file with mode: 0644]
branches/winverbs/tools/infiniband_diags/src/ibaddr/SOURCES [new file with mode: 0644]
branches/winverbs/tools/infiniband_diags/src/ibdiag_common.c [new file with mode: 0644]
branches/winverbs/tools/infiniband_diags/src/ibnetdiscover.c [new file with mode: 0644]
branches/winverbs/tools/infiniband_diags/src/ibnetdiscover/SOURCES [new file with mode: 0644]
branches/winverbs/tools/infiniband_diags/src/ibping.c [new file with mode: 0644]
branches/winverbs/tools/infiniband_diags/src/ibping/SOURCES [new file with mode: 0644]
branches/winverbs/tools/infiniband_diags/src/ibportstate.c [new file with mode: 0644]
branches/winverbs/tools/infiniband_diags/src/ibroute.c [new file with mode: 0644]
branches/winverbs/tools/infiniband_diags/src/ibsendtrap.c [new file with mode: 0644]
branches/winverbs/tools/infiniband_diags/src/ibstat.c [new file with mode: 0644]
branches/winverbs/tools/infiniband_diags/src/ibstat/SOURCES [new file with mode: 0644]
branches/winverbs/tools/infiniband_diags/src/ibsysstat.c [new file with mode: 0644]
branches/winverbs/tools/infiniband_diags/src/ibtracert.c [new file with mode: 0644]
branches/winverbs/tools/infiniband_diags/src/mcm_rereg_test.c [new file with mode: 0644]
branches/winverbs/tools/infiniband_diags/src/perfquery.c [new file with mode: 0644]
branches/winverbs/tools/infiniband_diags/src/perfquery/SOURCES [new file with mode: 0644]
branches/winverbs/tools/infiniband_diags/src/saquery.c [new file with mode: 0644]
branches/winverbs/tools/infiniband_diags/src/saquery/SOURCES [new file with mode: 0644]
branches/winverbs/tools/infiniband_diags/src/sminfo.c [new file with mode: 0644]
branches/winverbs/tools/infiniband_diags/src/sminfo/SOURCES [new file with mode: 0644]
branches/winverbs/tools/infiniband_diags/src/smpdump.c [new file with mode: 0644]
branches/winverbs/tools/infiniband_diags/src/smpquery.c [new file with mode: 0644]
branches/winverbs/tools/infiniband_diags/src/vendstat.c [new file with mode: 0644]
branches/winverbs/tools/infiniband_diags/src/vendstat/SOURCES [new file with mode: 0644]

diff --git a/branches/winverbs/tools/infiniband_diags/dirs b/branches/winverbs/tools/infiniband_diags/dirs
new file mode 100644 (file)
index 0000000..039a6ee
--- /dev/null
@@ -0,0 +1,2 @@
+DIRS = \\r
+       src
\ No newline at end of file
diff --git a/branches/winverbs/tools/infiniband_diags/include/grouping.h b/branches/winverbs/tools/infiniband_diags/include/grouping.h
new file mode 100644 (file)
index 0000000..1044f3a
--- /dev/null
@@ -0,0 +1,112 @@
+/*\r
+ * Copyright (c) 2004-2007 Voltaire Inc.  All rights reserved.\r
+ * Copyright (c) 2007 Xsigo Systems 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 _GROUPING_H_\r
+#define _GROUPING_H_\r
+\r
+/*========================================================*/\r
+/*               FABRIC SCANNER SPECIFIC DATA             */\r
+/*========================================================*/\r
+\r
+#define SPINES_MAX_NUM 12\r
+#define LINES_MAX_NUM 36\r
+\r
+typedef struct ChassisList ChassisList;\r
+typedef struct AllChassisList AllChassisList;\r
+\r
+struct ChassisList {\r
+       ChassisList *next;\r
+       uint64_t chassisguid;\r
+       int chassisnum;\r
+       int chassistype;\r
+       int nodecount;          /* used for grouping by SystemImageGUID */\r
+       Node *spinenode[SPINES_MAX_NUM + 1];\r
+       Node *linenode[LINES_MAX_NUM + 1];\r
+};\r
+\r
+struct AllChassisList {\r
+       ChassisList *first;\r
+       ChassisList *current;\r
+       ChassisList *last;\r
+};\r
+\r
+/*========================================================*/\r
+/*                CHASSIS RECOGNITION SPECIFIC DATA       */\r
+/*========================================================*/\r
+\r
+/* Device IDs */\r
+#define VTR_DEVID_IB_FC_ROUTER         0x5a00\r
+#define VTR_DEVID_IB_IP_ROUTER         0x5a01\r
+#define VTR_DEVID_ISR9600_SPINE                0x5a02\r
+#define VTR_DEVID_ISR9600_LEAF         0x5a03\r
+#define VTR_DEVID_HCA1                 0x5a04\r
+#define VTR_DEVID_HCA2                 0x5a44\r
+#define VTR_DEVID_HCA3                 0x6278\r
+#define VTR_DEVID_SW_6IB4              0x5a05\r
+#define VTR_DEVID_ISR9024              0x5a06\r
+#define VTR_DEVID_ISR9288              0x5a07\r
+#define VTR_DEVID_SLB24                        0x5a09\r
+#define VTR_DEVID_SFB12                        0x5a08\r
+#define VTR_DEVID_SFB4                 0x5a0b\r
+#define VTR_DEVID_ISR9024_12           0x5a0c\r
+#define VTR_DEVID_SLB8                 0x5a0d\r
+#define VTR_DEVID_RLX_SWITCH_BLADE     0x5a20\r
+#define VTR_DEVID_ISR9024_DDR          0x5a31\r
+#define VTR_DEVID_SFB12_DDR            0x5a32\r
+#define VTR_DEVID_SFB4_DDR             0x5a33\r
+#define VTR_DEVID_SLB24_DDR            0x5a34\r
+#define VTR_DEVID_SFB2012              0x5a37\r
+#define VTR_DEVID_SLB2024              0x5a38\r
+#define VTR_DEVID_ISR2012              0x5a39\r
+#define VTR_DEVID_SFB2004              0x5a40\r
+#define VTR_DEVID_ISR2004              0x5a41\r
+\r
+enum ChassisType { UNRESOLVED_CT, ISR9288_CT, ISR9096_CT, ISR2012_CT, ISR2004_CT };\r
+enum ChassisSlot { UNRESOLVED_CS, LINE_CS, SPINE_CS, SRBD_CS };\r
+\r
+/*========================================================*/\r
+/*                External interface                      */\r
+/*========================================================*/\r
+\r
+ChassisList *group_nodes();\r
+char *portmapstring(Port *port);\r
+char *get_chassis_type(unsigned char chassistype);\r
+char *get_chassis_slot(unsigned char chassisslot);\r
+uint64_t get_chassis_guid(unsigned char chassisnum);\r
+\r
+int is_xsigo_guid(uint64_t guid);\r
+int is_xsigo_tca(uint64_t guid);\r
+int is_xsigo_hca(uint64_t guid);\r
+\r
+#endif /* _GROUPING_H_ */\r
diff --git a/branches/winverbs/tools/infiniband_diags/include/ibdiag_common.h b/branches/winverbs/tools/infiniband_diags/include/ibdiag_common.h
new file mode 100644 (file)
index 0000000..1ed5758
--- /dev/null
@@ -0,0 +1,65 @@
+/*\r
+ * Copyright (c) 2006-2007 The Regents of the University of California.\r
+ * Copyright (c) 2004-2008 Voltaire 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 _IBDIAG_COMMON_H_\r
+#define _IBDIAG_COMMON_H_\r
+\r
+#include <stdio.h>\r
+\r
+#if !defined( __cplusplus )\r
+#define inline __inline\r
+#endif\r
+\r
+extern char *argv0;\r
+extern int   ibdebug;\r
+\r
+/*========================================================*/\r
+/*                External interface                      */\r
+/*========================================================*/\r
+\r
+void  iberror(const char *fn, char *msg, ...);\r
+\r
+#undef DEBUG\r
+#define        DEBUG   if (ibdebug || verbose) IBWARN\r
+#define        VERBOSE if (ibdebug || verbose > 1) IBWARN\r
+#define IBERROR(fmt, ...) iberror(__FUNCTION__, fmt, ## __VA_ARGS__)\r
+\r
+#include <ibdiag_version.h>\r
+\r
+static inline const char* get_build_version(void) \r
+{ \r
+       return "BUILD VERSION: " IBDIAG_VERSION " Build date: " __DATE__ " " __TIME__ ;\r
+}\r
+\r
+#endif /* _IBDIAG_COMMON_H_ */\r
diff --git a/branches/winverbs/tools/infiniband_diags/include/ibdiag_version.h b/branches/winverbs/tools/infiniband_diags/include/ibdiag_version.h
new file mode 100644 (file)
index 0000000..790385f
--- /dev/null
@@ -0,0 +1,39 @@
+/*\r
+ * Copyright (c) 2008 Voltaire 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 _IBDIAG_VERSION_H_\r
+#define _IBDIAG_VERSION_H_\r
+\r
+#define IBDIAG_VERSION "1.4.2"\r
+\r
+#endif /* _IBDIAG_VERSION_H_ */\r
diff --git a/branches/winverbs/tools/infiniband_diags/include/ibdiag_version.h.in b/branches/winverbs/tools/infiniband_diags/include/ibdiag_version.h.in
new file mode 100644 (file)
index 0000000..fd842e6
--- /dev/null
@@ -0,0 +1,39 @@
+/*\r
+ * Copyright (c) 2008 Voltaire 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 _IBDIAG_VERSION_H_\r
+#define _IBDIAG_VERSION_H_\r
+\r
+#define IBDIAG_VERSION "@VERSION@"\r
+\r
+#endif /* _IBDIAG_VERSION_H_ */\r
diff --git a/branches/winverbs/tools/infiniband_diags/include/ibnetdiscover.h b/branches/winverbs/tools/infiniband_diags/include/ibnetdiscover.h
new file mode 100644 (file)
index 0000000..c52cad5
--- /dev/null
@@ -0,0 +1,107 @@
+/*\r
+ * Copyright (c) 2004-2007 Voltaire Inc.  All rights reserved.\r
+ * Copyright (c) 2007 Xsigo Systems 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 _IBNETDISCOVER_H_\r
+#define _IBNETDISCOVER_H_\r
+\r
+#define MAXHOPS                63\r
+\r
+#define CA_NODE                1\r
+#define SWITCH_NODE    2\r
+#define ROUTER_NODE    3\r
+\r
+#define LIST_CA_NODE    (1 << CA_NODE)\r
+#define LIST_SWITCH_NODE (1 << SWITCH_NODE)\r
+#define LIST_ROUTER_NODE (1 << ROUTER_NODE)\r
+\r
+/* Vendor IDs (for chassis based systems) */\r
+#define VTR_VENDOR_ID                  0x8f1   /* Voltaire */\r
+#define TS_VENDOR_ID                   0x5ad   /* Cisco */\r
+#define SS_VENDOR_ID                   0x66a   /* InfiniCon */\r
+#define XS_VENDOR_ID                   0x1397  /* Xsigo */\r
+\r
+\r
+typedef struct Port Port;\r
+typedef struct Node Node;\r
+typedef struct ChassisRecord ChassisRecord;\r
+\r
+struct ChassisRecord {\r
+       ChassisRecord *next;\r
+\r
+       unsigned char chassisnum;\r
+       unsigned char anafanum;\r
+       unsigned char slotnum;\r
+       unsigned char chassistype;\r
+       unsigned char chassisslot;\r
+};\r
+\r
+struct Port {\r
+       Port *next;\r
+       uint64_t portguid;\r
+       int portnum;\r
+       int lid;\r
+       int lmc;\r
+       int state;\r
+       int physstate;\r
+       int linkwidth;\r
+       int linkspeed;\r
+\r
+       Node *node;\r
+       Port *remoteport;               /* null if SMA */\r
+};\r
+\r
+struct Node {\r
+       Node *htnext;\r
+       Node *dnext;\r
+       Port *ports;\r
+       ib_portid_t path;\r
+       int type;\r
+       int dist;\r
+       int numports;\r
+       int localport;\r
+       int smalid;\r
+       int smalmc;\r
+       int smaenhsp0;\r
+       uint32_t devid;\r
+       uint32_t vendid;\r
+       uint64_t sysimgguid;\r
+       uint64_t nodeguid;\r
+       uint64_t portguid;\r
+       char nodedesc[64];\r
+       uint8_t nodeinfo[64];\r
+\r
+       ChassisRecord *chrecord;\r
+};\r
+\r
+#endif /* _IBNETDISCOVER_H_ */\r
diff --git a/branches/winverbs/tools/infiniband_diags/src/dirs b/branches/winverbs/tools/infiniband_diags/src/dirs
new file mode 100644 (file)
index 0000000..23d2382
--- /dev/null
@@ -0,0 +1,13 @@
+DIRS =                 \\r
+       sminfo          \\r
+       ibstat          \\r
+       perfquery       \\r
+       vendstat        \\r
+       ibaddr\r
+       \r
+       \r
+       \r
+       \r
+       \r
+       \r
+               
\ No newline at end of file
diff --git a/branches/winverbs/tools/infiniband_diags/src/grouping.c b/branches/winverbs/tools/infiniband_diags/src/grouping.c
new file mode 100644 (file)
index 0000000..93b6f09
--- /dev/null
@@ -0,0 +1,793 @@
+/*\r
+ * Copyright (c) 2004-2007 Voltaire Inc.  All rights reserved.\r
+ * Copyright (c) 2007 Xsigo Systems 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
+/*========================================================*/\r
+/*               FABRIC SCANNER SPECIFIC DATA             */\r
+/*========================================================*/\r
+\r
+#if HAVE_CONFIG_H\r
+#  include <config.h>\r
+#endif /* HAVE_CONFIG_H */\r
+\r
+#include <stdlib.h>\r
+\r
+#if defined(_WIN32) || defined(_WIN64)\r
+#include <windows.h>\r
+#include <winsock2.h>\r
+#include "..\ibdiag_common.c"\r
+#else\r
+#include <stdint.h>\r
+#include <inttypes.h>\r
+#endif\r
+\r
+#include <infiniband/common.h>\r
+#include <infiniband/mad.h>\r
+\r
+#include "ibnetdiscover.h"\r
+#include "grouping.h"\r
+\r
+#define OUT_BUFFER_SIZE 16\r
+\r
+\r
+extern Node *nodesdist[MAXHOPS+1];     /* last is CA list */\r
+extern Node *mynode;\r
+extern Port *myport;\r
+extern int maxhops_discovered;\r
+\r
+AllChassisList mylist;\r
+\r
+char *ChassisTypeStr[5] = { "", "ISR9288", "ISR9096", "ISR2012", "ISR2004" };\r
+char *ChassisSlotStr[4] = { "", "Line", "Spine", "SRBD" };\r
+\r
+\r
+char *get_chassis_type(unsigned char chassistype)\r
+{\r
+       if (chassistype == UNRESOLVED_CT || chassistype > ISR2004_CT)\r
+               return NULL;\r
+       return ChassisTypeStr[chassistype];\r
+}\r
+\r
+char *get_chassis_slot(unsigned char chassisslot)\r
+{\r
+       if (chassisslot == UNRESOLVED_CS || chassisslot > SRBD_CS)\r
+               return NULL;\r
+       return ChassisSlotStr[chassisslot];\r
+}\r
+\r
+static struct ChassisList *find_chassisnum(unsigned char chassisnum)\r
+{\r
+       ChassisList *current;\r
+\r
+       for (current = mylist.first; current; current = current->next) {\r
+               if (current->chassisnum == chassisnum)\r
+                       return current;\r
+       }\r
+\r
+       return NULL;\r
+}\r
+\r
+static uint64_t topspin_chassisguid(uint64_t guid)\r
+{\r
+       /* Byte 3 in system image GUID is chassis type, and */\r
+       /* Byte 4 is location ID (slot) so just mask off byte 4 */\r
+       return guid & 0xffffffff00ffffffULL;\r
+}\r
+\r
+int is_xsigo_guid(uint64_t guid)\r
+{\r
+       if ((guid & 0xffffff0000000000ULL) == 0x0013970000000000ULL)\r
+               return 1;\r
+       else\r
+               return 0;\r
+}\r
+\r
+static int is_xsigo_leafone(uint64_t guid)\r
+{\r
+       if ((guid & 0xffffffffff000000ULL) == 0x0013970102000000ULL)\r
+               return 1;\r
+       else\r
+               return 0;\r
+}\r
+\r
+int is_xsigo_hca(uint64_t guid)\r
+{\r
+       /* NodeType 2 is HCA */\r
+       if ((guid & 0xffffffff00000000ULL) == 0x0013970200000000ULL)\r
+               return 1;\r
+       else\r
+               return 0;\r
+}\r
+\r
+int is_xsigo_tca(uint64_t guid)\r
+{\r
+       /* NodeType 3 is TCA */\r
+       if ((guid & 0xffffffff00000000ULL) == 0x0013970300000000ULL)\r
+               return 1;\r
+       else\r
+               return 0;\r
+}\r
+\r
+static int is_xsigo_ca(uint64_t guid)\r
+{\r
+       if (is_xsigo_hca(guid) || is_xsigo_tca(guid))\r
+               return 1;\r
+       else\r
+               return 0;\r
+}\r
+\r
+static int is_xsigo_switch(uint64_t guid)\r
+{\r
+       if ((guid & 0xffffffff00000000ULL) == 0x0013970100000000ULL)\r
+               return 1;\r
+       else\r
+               return 0;\r
+}\r
+\r
+static uint64_t xsigo_chassisguid(Node *node)\r
+{\r
+       if (!is_xsigo_ca(node->sysimgguid)) {\r
+               /* Byte 3 is NodeType and byte 4 is PortType */\r
+               /* If NodeType is 1 (switch), PortType is masked */\r
+               if (is_xsigo_switch(node->sysimgguid))\r
+                       return node->sysimgguid & 0xffffffff00ffffffULL;\r
+               else\r
+                       return node->sysimgguid;\r
+       } else {\r
+               /* Is there a peer port ? */\r
+               if (!node->ports->remoteport)\r
+                       return node->sysimgguid;\r
+\r
+               /* If peer port is Leaf 1, use its chassis GUID */\r
+               if (is_xsigo_leafone(node->ports->remoteport->node->sysimgguid))\r
+                       return node->ports->remoteport->node->sysimgguid &\r
+                              0xffffffff00ffffffULL;\r
+               else\r
+                       return node->sysimgguid;\r
+       }\r
+}\r
+\r
+static uint64_t get_chassisguid(Node *node)\r
+{\r
+       if (node->vendid == TS_VENDOR_ID || node->vendid == SS_VENDOR_ID)\r
+               return topspin_chassisguid(node->sysimgguid);\r
+       else if (node->vendid == XS_VENDOR_ID || is_xsigo_guid(node->sysimgguid))\r
+               return xsigo_chassisguid(node);\r
+       else\r
+               return node->sysimgguid;\r
+}\r
+\r
+static struct ChassisList *find_chassisguid(Node *node)\r
+{\r
+       ChassisList *current;\r
+       uint64_t chguid;\r
+\r
+       chguid = get_chassisguid(node);\r
+       for (current = mylist.first; current; current = current->next) {\r
+               if (current->chassisguid == chguid)\r
+                       return current;\r
+       }\r
+\r
+       return NULL;\r
+}\r
+\r
+uint64_t get_chassis_guid(unsigned char chassisnum)\r
+{\r
+       ChassisList *chassis;\r
+\r
+       chassis = find_chassisnum(chassisnum);\r
+       if (chassis)\r
+               return chassis->chassisguid;\r
+       else\r
+               return 0;\r
+}\r
+\r
+static int is_router(Node *node)\r
+{\r
+       return (node->devid == VTR_DEVID_IB_FC_ROUTER ||\r
+               node->devid == VTR_DEVID_IB_IP_ROUTER);\r
+}\r
+\r
+static int is_spine_9096(Node *node)\r
+{\r
+       return (node->devid == VTR_DEVID_SFB4 ||\r
+               node->devid == VTR_DEVID_SFB4_DDR);\r
+}\r
+\r
+static int is_spine_9288(Node *node)\r
+{\r
+       return (node->devid == VTR_DEVID_SFB12 ||\r
+               node->devid == VTR_DEVID_SFB12_DDR);\r
+}\r
+\r
+static int is_spine_2004(Node *node)\r
+{\r
+       return (node->devid == VTR_DEVID_SFB2004);\r
+}\r
+\r
+static int is_spine_2012(Node *node)\r
+{\r
+       return (node->devid == VTR_DEVID_SFB2012);\r
+}\r
+\r
+static int is_spine(Node *node)\r
+{\r
+       return (is_spine_9096(node) || is_spine_9288(node) ||\r
+               is_spine_2004(node) || is_spine_2012(node));\r
+}\r
+\r
+static int is_line_24(Node *node)\r
+{\r
+       return (node->devid == VTR_DEVID_SLB24 ||\r
+               node->devid == VTR_DEVID_SLB24_DDR);\r
+}\r
+\r
+static int is_line_8(Node *node)\r
+{\r
+       return (node->devid == VTR_DEVID_SLB8);\r
+}\r
+\r
+static int is_line_2024(Node *node)\r
+{\r
+       return (node->devid == VTR_DEVID_SLB2024);\r
+}\r
+\r
+static int is_line(Node *node)\r
+{\r
+       return (is_line_24(node) || is_line_8(node) || is_line_2024(node));\r
+}\r
+\r
+int is_chassis_switch(Node *node)\r
+{\r
+    return (is_spine(node) || is_line(node));\r
+}\r
+\r
+/* these structs help find Line (Anafa) slot number while using spine portnum */\r
+int 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 };\r
+int 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 };\r
+int 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 };\r
+int 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 };\r
+\r
+/* IPR FCR modules connectivity while using sFB4 port as reference */\r
+int 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 };\r
+\r
+/* these structs help find Spine (Anafa) slot number while using spine portnum */\r
+int 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 };\r
+int 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 };\r
+int 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 };\r
+int 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 };\r
+/*     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 }; */\r
+\r
+static void get_sfb_slot(Node *node, Port *lineport)\r
+{\r
+       ChassisRecord *ch = node->chrecord;\r
+\r
+       ch->chassisslot = SPINE_CS;\r
+       if (is_spine_9096(node)) {\r
+               ch->chassistype = ISR9096_CT;\r
+               ch->slotnum = spine4_slot_2_slb[lineport->portnum];\r
+               ch->anafanum = anafa_spine4_slot_2_slb[lineport->portnum];\r
+       } else if (is_spine_9288(node)) {\r
+               ch->chassistype = ISR9288_CT;\r
+               ch->slotnum = spine12_slot_2_slb[lineport->portnum];\r
+               ch->anafanum = anafa_spine12_slot_2_slb[lineport->portnum];\r
+       } else if (is_spine_2012(node)) {\r
+               ch->chassistype = ISR2012_CT;\r
+               ch->slotnum = spine12_slot_2_slb[lineport->portnum];\r
+               ch->anafanum = anafa_spine12_slot_2_slb[lineport->portnum];\r
+       } else if (is_spine_2004(node)) {\r
+               ch->chassistype = ISR2004_CT;\r
+               ch->slotnum = spine4_slot_2_slb[lineport->portnum];\r
+               ch->anafanum = anafa_spine4_slot_2_slb[lineport->portnum];\r
+       } else {\r
+               IBPANIC("Unexpected node found: guid 0x%016" PRIx64, node->nodeguid);\r
+       }\r
+}\r
+\r
+static void get_router_slot(Node *node, Port *spineport)\r
+{\r
+       ChassisRecord *ch = node->chrecord;\r
+       int guessnum = 0;\r
+\r
+       if (!ch) {\r
+               if (!(node->chrecord = calloc(1, sizeof(ChassisRecord))))\r
+                       IBPANIC("out of mem");\r
+               ch = node->chrecord;\r
+       }\r
+\r
+       ch->chassisslot = SRBD_CS;\r
+       if (is_spine_9096(spineport->node)) {\r
+               ch->chassistype = ISR9096_CT;\r
+               ch->slotnum = line_slot_2_sfb4[spineport->portnum];\r
+               ch->anafanum = ipr_slot_2_sfb4_port[spineport->portnum];\r
+       } else if (is_spine_9288(spineport->node)) {\r
+               ch->chassistype = ISR9288_CT;\r
+               ch->slotnum = line_slot_2_sfb12[spineport->portnum];\r
+               /* this is a smart guess based on nodeguids order on sFB-12 module */\r
+               guessnum = spineport->node->nodeguid % 4;\r
+               /* module 1 <--> remote anafa 3 */\r
+               /* module 2 <--> remote anafa 2 */\r
+               /* module 3 <--> remote anafa 1 */\r
+               ch->anafanum = (guessnum == 3 ? 1 : (guessnum == 1 ? 3 : 2));\r
+       } else if (is_spine_2012(spineport->node)) {\r
+               ch->chassistype = ISR2012_CT;\r
+               ch->slotnum = line_slot_2_sfb12[spineport->portnum];\r
+               /* this is a smart guess based on nodeguids order on sFB-12 module */\r
+               guessnum = spineport->node->nodeguid % 4;\r
+               // module 1 <--> remote anafa 3\r
+               // module 2 <--> remote anafa 2\r
+               // module 3 <--> remote anafa 1\r
+               ch->anafanum = (guessnum == 3? 1 : (guessnum == 1 ? 3 : 2));\r
+       } else if (is_spine_2004(spineport->node)) {\r
+               ch->chassistype = ISR2004_CT;\r
+               ch->slotnum = line_slot_2_sfb4[spineport->portnum];\r
+               ch->anafanum = ipr_slot_2_sfb4_port[spineport->portnum];\r
+       } else {\r
+               IBPANIC("Unexpected node found: guid 0x%016" PRIx64, spineport->node->nodeguid);\r
+       }\r
+}\r
+\r
+static void get_slb_slot(ChassisRecord *ch, Port *spineport)\r
+{\r
+       ch->chassisslot = LINE_CS;\r
+       if (is_spine_9096(spineport->node)) {\r
+               ch->chassistype = ISR9096_CT;\r
+               ch->slotnum = line_slot_2_sfb4[spineport->portnum];\r
+               ch->anafanum = anafa_line_slot_2_sfb4[spineport->portnum];\r
+       } else if (is_spine_9288(spineport->node)) {\r
+               ch->chassistype = ISR9288_CT;\r
+               ch->slotnum = line_slot_2_sfb12[spineport->portnum];\r
+               ch->anafanum = anafa_line_slot_2_sfb12[spineport->portnum];\r
+       } else if (is_spine_2012(spineport->node)) {\r
+               ch->chassistype = ISR2012_CT;\r
+               ch->slotnum = line_slot_2_sfb12[spineport->portnum];\r
+               ch->anafanum = anafa_line_slot_2_sfb12[spineport->portnum];\r
+       } else if (is_spine_2004(spineport->node)) {\r
+               ch->chassistype = ISR2004_CT;\r
+               ch->slotnum = line_slot_2_sfb4[spineport->portnum];\r
+               ch->anafanum = anafa_line_slot_2_sfb4[spineport->portnum];\r
+       } else {\r
+               IBPANIC("Unexpected node found: guid 0x%016" PRIx64, spineport->node->nodeguid);\r
+       }\r
+}\r
+\r
+/*\r
+       This function called for every Voltaire node in fabric\r
+       It could be optimized so, but time overhead is very small\r
+       and its only diag.util\r
+*/\r
+static void fill_chassis_record(Node *node)\r
+{\r
+       Port *port;\r
+       Node *remnode = 0;\r
+       ChassisRecord *ch = 0;\r
+\r
+       if (node->chrecord) /* somehow this node has already been passed */\r
+               return;\r
+\r
+       if (!(node->chrecord = calloc(1, sizeof(ChassisRecord))))\r
+               IBPANIC("out of mem");\r
+\r
+       ch = node->chrecord;\r
+\r
+       /* node is router only in case of using unique lid */\r
+       /* (which is lid of chassis router port) */\r
+       /* in such case node->ports is actually a requested port... */\r
+       if (is_router(node) && is_spine(node->ports->remoteport->node))\r
+               get_router_slot(node, node->ports->remoteport);\r
+       else if (is_spine(node)) {\r
+               for (port = node->ports; port; port = port->next) {\r
+                       if (!port->remoteport)\r
+                               continue;\r
+                       remnode = port->remoteport->node;\r
+                       if (remnode->type != SWITCH_NODE) {\r
+                               if (!remnode->chrecord)\r
+                                       get_router_slot(remnode, port);\r
+                               continue;\r
+                       }\r
+                       if (!ch->chassistype)\r
+                               /* we assume here that remoteport belongs to line */\r
+                               get_sfb_slot(node, port->remoteport);\r
+\r
+                               /* we could break here, but need to find if more routers connected */\r
+               }\r
+\r
+       } else if (is_line(node)) {\r
+               for (port = node->ports; port; port = port->next) {\r
+                       if (port->portnum > 12)\r
+                               continue;\r
+                       if (!port->remoteport)\r
+                               continue;\r
+                       /* we assume here that remoteport belongs to spine */\r
+                       get_slb_slot(ch, port->remoteport);\r
+                       break;\r
+               }\r
+       }\r
+\r
+       return;\r
+}\r
+\r
+static int get_line_index(Node *node)\r
+{\r
+       int retval = 3 * (node->chrecord->slotnum - 1) + node->chrecord->anafanum;\r
+\r
+       if (retval > LINES_MAX_NUM || retval < 1)\r
+               IBPANIC("Internal error");\r
+       return retval;\r
+}\r
+\r
+static int get_spine_index(Node *node)\r
+{\r
+       int retval;\r
+\r
+       if (is_spine_9288(node) || is_spine_2012(node))\r
+               retval = 3 * (node->chrecord->slotnum - 1) + node->chrecord->anafanum;\r
+       else\r
+               retval = node->chrecord->slotnum;\r
+\r
+       if (retval > SPINES_MAX_NUM || retval < 1)\r
+               IBPANIC("Internal error");\r
+       return retval;\r
+}\r
+\r
+static void insert_line_router(Node *node, ChassisList *chassislist)\r
+{\r
+       int i = get_line_index(node);\r
+\r
+       if (chassislist->linenode[i])\r
+               return;         /* already filled slot */\r
+\r
+       chassislist->linenode[i] = node;\r
+       node->chrecord->chassisnum = chassislist->chassisnum;\r
+}\r
+\r
+static void insert_spine(Node *node, ChassisList *chassislist)\r
+{\r
+       int i = get_spine_index(node);\r
+\r
+       if (chassislist->spinenode[i])\r
+               return;         /* already filled slot */\r
+\r
+       chassislist->spinenode[i] = node;\r
+       node->chrecord->chassisnum = chassislist->chassisnum;\r
+}\r
+\r
+static void pass_on_lines_catch_spines(ChassisList *chassislist)\r
+{\r
+       Node *node, *remnode;\r
+       Port *port;\r
+       int i;\r
+\r
+       for (i = 1; i <= LINES_MAX_NUM; i++) {\r
+               node = chassislist->linenode[i];\r
+\r
+               if (!(node && is_line(node)))\r
+                       continue;       /* empty slot or router */\r
+\r
+               for (port = node->ports; port; port = port->next) {\r
+                       if (port->portnum > 12)\r
+                               continue;\r
+\r
+                       if (!port->remoteport)\r
+                               continue;\r
+                       remnode = port->remoteport->node;\r
+\r
+                       if (!remnode->chrecord)\r
+                               continue;       /* some error - spine not initialized ? FIXME */\r
+                       insert_spine(remnode, chassislist);\r
+               }\r
+       }\r
+}\r
+\r
+static void pass_on_spines_catch_lines(ChassisList *chassislist)\r
+{\r
+       Node *node, *remnode;\r
+       Port *port;\r
+       int i;\r
+\r
+       for (i = 1; i <= SPINES_MAX_NUM; i++) {\r
+               node = chassislist->spinenode[i];\r
+               if (!node)\r
+                       continue;       /* empty slot */\r
+               for (port = node->ports; port; port = port->next) {\r
+                       if (!port->remoteport)\r
+                               continue;\r
+                       remnode = port->remoteport->node;\r
+\r
+                       if (!remnode->chrecord)\r
+                               continue;       /* some error - line/router not initialized ? FIXME */\r
+                       insert_line_router(remnode, chassislist);\r
+               }\r
+       }\r
+}\r
+\r
+/*\r
+       Stupid interpolation algorithm...\r
+       But nothing to do - have to be compliant with VoltaireSM/NMS\r
+*/\r
+static void pass_on_spines_interpolate_chguid(ChassisList *chassislist)\r
+{\r
+       Node *node;\r
+       int i;\r
+\r
+       for (i = 1; i <= SPINES_MAX_NUM; i++) {\r
+               node = chassislist->spinenode[i];\r
+               if (!node)\r
+                       continue;       /* skip the empty slots */\r
+\r
+               /* take first guid minus one to be consistent with SM */\r
+               chassislist->chassisguid = node->nodeguid - 1;\r
+               break;\r
+       }\r
+}\r
+\r
+/*\r
+       This function fills chassislist structure with all nodes\r
+       in that chassis\r
+       chassislist structure = structure of one standalone chassis\r
+*/\r
+static void build_chassis(Node *node, ChassisList *chassislist)\r
+{\r
+       Node *remnode = 0;\r
+       Port *port = 0;\r
+\r
+       /* we get here with node = chassis_spine */\r
+       chassislist->chassistype = node->chrecord->chassistype;\r
+       insert_spine(node, chassislist);\r
+\r
+       /* loop: pass on all ports of node */\r
+       for (port = node->ports; port; port = port->next) {\r
+               if (!port->remoteport)\r
+                       continue;\r
+               remnode = port->remoteport->node;\r
+\r
+               if (!remnode->chrecord)\r
+                       continue; /* some error - line or router not initialized ? FIXME */\r
+\r
+               insert_line_router(remnode, chassislist);\r
+       }\r
+\r
+       pass_on_lines_catch_spines(chassislist);\r
+       /* this pass needed for to catch routers, since routers connected only */\r
+       /* to spines in slot 1 or 4 and we could miss them first time */\r
+       pass_on_spines_catch_lines(chassislist);\r
+\r
+       /* additional 2 passes needed for to overcome a problem of pure "in-chassis" */\r
+       /* connectivity - extra pass to ensure that all related chips/modules */\r
+       /* inserted into the chassislist */\r
+       pass_on_lines_catch_spines(chassislist);\r
+       pass_on_spines_catch_lines(chassislist);\r
+       pass_on_spines_interpolate_chguid(chassislist);\r
+}\r
+\r
+/*========================================================*/\r
+/*                INTERNAL TO EXTERNAL PORT MAPPING       */\r
+/*========================================================*/\r
+\r
+/*\r
+Description : On ISR9288/9096 external ports indexing\r
+              is not matching the internal ( anafa ) port\r
+              indexes. Use this MAP to translate the data you get from\r
+              the OpenIB diagnostics (smpquery, ibroute, ibtracert, etc.)\r
+\r
+\r
+Module : sLB-24\r
+                anafa 1             anafa 2\r
+ext port | 13 14 15 16 17 18 | 19 20 21 22 23 24\r
+int port | 22 23 24 18 17 16 | 22 23 24 18 17 16\r
+ext port | 1  2  3  4  5  6  | 7  8  9  10 11 12\r
+int port | 19 20 21 15 14 13 | 19 20 21 15 14 13\r
+------------------------------------------------\r
+\r
+Module : sLB-8\r
+                anafa 1             anafa 2\r
+ext port | 13 14 15 16 17 18 | 19 20 21 22 23 24\r
+int port | 24 23 22 18 17 16 | 24 23 22 18 17 16\r
+ext port | 1  2  3  4  5  6  | 7  8  9  10 11 12\r
+int port | 21 20 19 15 14 13 | 21 20 19 15 14 13\r
+\r
+----------->\r
+                anafa 1             anafa 2\r
+ext port | -  -  5  -  -  6  | -  -  7  -  -  8\r
+int port | 24 23 22 18 17 16 | 24 23 22 18 17 16\r
+ext port | -  -  1  -  -  2  | -  -  3  -  -  4\r
+int port | 21 20 19 15 14 13 | 21 20 19 15 14 13\r
+------------------------------------------------\r
+\r
+Module : sLB-2024\r
+\r
+ext port | 13 14 15 16 17 18 19 20 21 22 23 24\r
+A1 int port| 13 14 15 16 17 18 19 20 21 22 23 24\r
+ext port | 1 2 3 4 5 6 7 8 9 10 11 12\r
+A2 int port| 13 14 15 16 17 18 19 20 21 22 23 24\r
+---------------------------------------------------\r
+\r
+*/\r
+\r
+int int2ext_map_slb24[2][25] = {\r
+                                       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 5, 4, 18, 17, 16, 1, 2, 3, 13, 14, 15 },\r
+                                       { 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 }\r
+                               };\r
+int int2ext_map_slb8[2][25] = {\r
+                                       { 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 },\r
+                                       { 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 }\r
+                               };\r
+int int2ext_map_slb2024[2][25] = {\r
+                                       { 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 },\r
+                                       { 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 }\r
+                               };\r
+/*     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 }; */\r
+\r
+/*\r
+       This function relevant only for line modules/chips\r
+       Returns string with external port index\r
+*/\r
+char *portmapstring(Port *port)\r
+{\r
+       static char mapping[OUT_BUFFER_SIZE];\r
+       ChassisRecord *ch = port->node->chrecord;\r
+       int portnum = port->portnum;\r
+       int chipnum = 0;\r
+       int pindex = 0;\r
+       Node *node = port->node;\r
+\r
+       if (!ch || !is_line(node) || (portnum < 13 || portnum > 24))\r
+               return NULL;\r
+\r
+       if (ch->anafanum < 1 || ch->anafanum > 2)\r
+               return NULL;\r
+\r
+       memset(mapping, 0, sizeof(mapping));\r
+\r
+       chipnum = ch->anafanum - 1;\r
+\r
+       if (is_line_24(node))\r
+               pindex = int2ext_map_slb24[chipnum][portnum];\r
+       else if (is_line_2024(node))\r
+               pindex = int2ext_map_slb2024[chipnum][portnum];\r
+       else\r
+               pindex = int2ext_map_slb8[chipnum][portnum];\r
+\r
+       sprintf(mapping, "[ext %d]", pindex);\r
+\r
+       return mapping;\r
+}\r
+\r
+static void add_chassislist()\r
+{\r
+       if (!(mylist.current = calloc(1, sizeof(ChassisList))))\r
+               IBPANIC("out of mem");\r
+\r
+       if (mylist.first == NULL) {\r
+               mylist.first = mylist.current;\r
+               mylist.last = mylist.current;\r
+       } else {\r
+               mylist.last->next = mylist.current;\r
+               mylist.current->next = NULL;\r
+               mylist.last = mylist.current;\r
+       }\r
+}\r
+\r
+/*\r
+       Main grouping function\r
+       Algorithm:\r
+       1. pass on every Voltaire node\r
+       2. catch spine chip for every Voltaire node\r
+               2.1 build/interpolate chassis around this chip\r
+               2.2 go to 1.\r
+       3. pass on non Voltaire nodes (SystemImageGUID based grouping)\r
+       4. now group non Voltaire nodes by SystemImageGUID\r
+*/\r
+ChassisList *group_nodes()\r
+{\r
+       Node *node;\r
+       int dist;\r
+       int chassisnum = 0;\r
+       struct ChassisList *chassis;\r
+\r
+       mylist.first = NULL;\r
+       mylist.current = NULL;\r
+       mylist.last = NULL;\r
+\r
+       /* first pass on switches and build for every Voltaire node */\r
+       /* an appropriate chassis record (slotnum and position) */\r
+       /* according to internal connectivity */\r
+       /* not very efficient but clear code so... */\r
+       for (dist = 0; dist <= maxhops_discovered; dist++) {\r
+               for (node = nodesdist[dist]; node; node = node->dnext) {\r
+                       if (node->vendid == VTR_VENDOR_ID)\r
+                               fill_chassis_record(node);\r
+               }\r
+       }\r
+\r
+       /* separate every Voltaire chassis from each other and build linked list of them */\r
+       /* algorithm: catch spine and find all surrounding nodes */\r
+       for (dist = 0; dist <= maxhops_discovered; dist++) {\r
+               for (node = nodesdist[dist]; node; node = node->dnext) {\r
+                       if (node->vendid != VTR_VENDOR_ID)\r
+                               continue;\r
+                       if (!node->chrecord || node->chrecord->chassisnum || !is_spine(node))\r
+                               continue;\r
+                       add_chassislist();\r
+                       mylist.current->chassisnum = ++chassisnum;\r
+                       build_chassis(node, mylist.current);\r
+               }\r
+       }\r
+\r
+       /* now make pass on nodes for chassis which are not Voltaire */\r
+       /* grouped by common SystemImageGUID */\r
+       for (dist = 0; dist <= maxhops_discovered; dist++) {\r
+               for (node = nodesdist[dist]; node; node = node->dnext) {\r
+                       if (node->vendid == VTR_VENDOR_ID)\r
+                               continue;\r
+                       if (node->sysimgguid) {\r
+                               chassis = find_chassisguid(node);\r
+                               if (chassis)\r
+                                       chassis->nodecount++;\r
+                               else {\r
+                                       /* Possible new chassis */\r
+                                       add_chassislist();\r
+                                       mylist.current->chassisguid = get_chassisguid(node);\r
+                                       mylist.current->nodecount = 1;\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+\r
+       /* now, make another pass to see which nodes are part of chassis */\r
+       /* (defined as chassis->nodecount > 1) */\r
+       for (dist = 0; dist <= MAXHOPS; ) {\r
+               for (node = nodesdist[dist]; node; node = node->dnext) {\r
+                       if (node->vendid == VTR_VENDOR_ID)\r
+                               continue;\r
+                       if (node->sysimgguid) {\r
+                               chassis = find_chassisguid(node);\r
+                               if (chassis && chassis->nodecount > 1) {\r
+                                       if (!chassis->chassisnum)\r
+                                               chassis->chassisnum = ++chassisnum;\r
+                                       if (!node->chrecord) {\r
+                                               if (!(node->chrecord = calloc(1, sizeof(ChassisRecord))))\r
+                                                       IBPANIC("out of mem");\r
+                                               node->chrecord->chassisnum = chassis->chassisnum;\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+               if (dist == maxhops_discovered)\r
+                       dist = MAXHOPS; /* skip to CAs */\r
+               else\r
+                       dist++;\r
+       }\r
+\r
+       return (mylist.first);\r
+}\r
diff --git a/branches/winverbs/tools/infiniband_diags/src/ibaddr.c b/branches/winverbs/tools/infiniband_diags/src/ibaddr.c
new file mode 100644 (file)
index 0000000..65e0308
--- /dev/null
@@ -0,0 +1,221 @@
+/*\r
+ * Copyright (c) 2004-2008 Voltaire 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
+#if HAVE_CONFIG_H\r
+#  include <config.h>\r
+#endif /* HAVE_CONFIG_H */\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#if defined(_WIN32) \r
+#include <windows.h>\r
+#include <winsock2.h>\r
+#include <ws2tcpip.h> \r
+#include "..\..\..\..\etc\user\getopt.c"\r
+#else\r
+#include <unistd.h>\r
+#include <stdarg.h>\r
+#include <getopt.h>\r
+#include <arpa/inet.h>\r
+#endif\r
+\r
+#include <infiniband/umad.h>\r
+#include <infiniband/mad.h>\r
+\r
+#include "ibdiag_common.h"\r
+\r
+char *argv0 = "ibaddr";\r
+\r
+static int\r
+ib_resolve_addr(ib_portid_t *portid, int portnum, int show_lid, int show_gid)\r
+{\r
+       char   gid_str[INET6_ADDRSTRLEN];\r
+       uint8_t portinfo[64];\r
+       uint8_t nodeinfo[64];\r
+       uint64_t guid, prefix;\r
+       ibmad_gid_t gid;\r
+       int lmc;\r
+\r
+       if (!smp_query(nodeinfo, portid, IB_ATTR_NODE_INFO, 0, 0))\r
+               return -1;\r
+\r
+       if (!smp_query(portinfo, portid, IB_ATTR_PORT_INFO, portnum, 0))\r
+               return -1;\r
+\r
+       mad_decode_field(portinfo, IB_PORT_LID_F, &portid->lid);\r
+       mad_decode_field(portinfo, IB_PORT_GID_PREFIX_F, &prefix);\r
+       mad_decode_field(portinfo, IB_PORT_LMC_F, &lmc);\r
+       mad_decode_field(nodeinfo, IB_NODE_PORT_GUID_F, &guid);\r
+\r
+       mad_encode_field(gid, IB_GID_PREFIX_F, &prefix);\r
+       mad_encode_field(gid, IB_GID_GUID_F, &guid);\r
+\r
+       if (show_gid) {\r
+               printf("GID %s ", inet_ntop(AF_INET6, gid, gid_str,\r
+                       sizeof gid_str));\r
+       }\r
+\r
+       if (show_lid > 0)\r
+               printf("LID start 0x%x end 0x%x", portid->lid, portid->lid + (1 << lmc) - 1);\r
+       else if (show_lid < 0)\r
+               printf("LID start %d end %d", portid->lid, portid->lid + (1 << lmc) - 1);\r
+       printf("\n");\r
+       return 0;\r
+}\r
+\r
+static void\r
+usage(void)\r
+{\r
+       char *basename;\r
+\r
+       if (!(basename = strrchr(argv0, '/')))\r
+               basename = argv0;\r
+       else\r
+               basename++;\r
+\r
+       fprintf(stderr, "Usage: %s [-d(ebug) -D(irect) -G(uid) -l(id_show) -g(id_show) -s(m_port) sm_lid -C ca_name -P ca_port "\r
+                       "-t(imeout) timeout_ms -V(ersion) -h(elp)] [<lid|dr_path|guid>]\n",\r
+                       basename);\r
+       fprintf(stderr, "\tExamples:\n");\r
+       fprintf(stderr, "\t\t%s\t\t\t# local port's address\n", basename);\r
+       fprintf(stderr, "\t\t%s 32\t\t# show lid range and gid of lid 32\n", basename);\r
+       fprintf(stderr, "\t\t%s -G 0x8f1040023\t# same but using guid address\n", basename);\r
+       fprintf(stderr, "\t\t%s -l 32\t\t# show lid range only\n", basename);\r
+       fprintf(stderr, "\t\t%s -L 32\t\t# show decimal lid range only\n", basename);\r
+       fprintf(stderr, "\t\t%s -g 32\t\t# show gid address only\n", basename);\r
+       exit(-1);\r
+}\r
+\r
+int __cdecl\r
+main(int argc, char **argv)\r
+{\r
+       int mgmt_classes[3] = {IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS};\r
+       ib_portid_t *sm_id = 0, sm_portid = {0};\r
+       ib_portid_t portid = {0};\r
+       extern int ibdebug;\r
+       int dest_type = IB_DEST_LID;\r
+       int timeout = 0;        /* use default */\r
+       int show_lid = 0, show_gid = 0;\r
+       int port = 0;\r
+       char *ca = 0;\r
+       int ca_port = 0;\r
+\r
+       static char str_opts[] = "C:P:t:s:dDGglLVhu";\r
+       static struct option long_opts[] = {\r
+               { "C", 1, 0, 'C'},\r
+               { "P", 1, 0, 'P'},\r
+               { "debug", 0, 0, 'd'},\r
+               { "Direct", 0, 0, 'D'},\r
+               { "Guid", 0, 0, 'G'},\r
+               { "gid_show", 0, 0, 'g'},\r
+               { "lid_show", 0, 0, 'l'},\r
+               { "Lid_show", 0, 0, 'L'},\r
+               { "timeout", 1, 0, 't'},\r
+               { "sm_port", 1, 0, 's'},\r
+               { "Version", 0, 0, 'V'},\r
+               { "help", 0, 0, 'h'},\r
+               { "usage", 0, 0, 'u'},\r
+               { 0 }\r
+       };\r
+\r
+       argv0 = argv[0];\r
+\r
+       while (1) {\r
+               int ch = getopt_long(argc, argv, str_opts, long_opts, NULL);\r
+               if ( ch == -1 )\r
+                       break;\r
+               switch(ch) {\r
+               case 'C':\r
+                       ca = optarg;\r
+                       break;\r
+               case 'P':\r
+                       ca_port = strtoul(optarg, 0, 0);\r
+                       break;\r
+               case 'd':\r
+                       ibdebug++;\r
+                       break;\r
+               case 'D':\r
+                       dest_type = IB_DEST_DRPATH;\r
+                       break;\r
+               case 'g':\r
+                       show_gid++;\r
+                       break;\r
+               case 'G':\r
+                       dest_type = IB_DEST_GUID;\r
+                       break;\r
+               case 'l':\r
+                       show_lid++;\r
+                       break;\r
+               case 'L':\r
+                       show_lid = -100;\r
+                       break;\r
+               case 's':\r
+                       if (ib_resolve_portid_str(&sm_portid, optarg, IB_DEST_LID, 0) < 0)\r
+                               IBERROR("can't resolve SM destination port %s", optarg);\r
+                       sm_id = &sm_portid;\r
+                       break;\r
+               case 't':\r
+                       timeout = strtoul(optarg, 0, 0);\r
+                       madrpc_set_timeout(timeout);\r
+                       break;\r
+               case 'V':\r
+                       fprintf(stderr, "%s %s\n", argv0, get_build_version() );\r
+                       exit(-1);\r
+               default:\r
+                       usage();\r
+                       break;\r
+               }\r
+       }\r
+       argc -= optind;\r
+       argv += optind;\r
+\r
+       if (argc > 1)\r
+               port = strtoul(argv[1], 0, 0);\r
+\r
+       if (!show_lid && !show_gid)\r
+               show_lid = show_gid = 1;\r
+\r
+       madrpc_init(ca, ca_port, mgmt_classes, 3);\r
+\r
+       if (argc) {\r
+               if (ib_resolve_portid_str(&portid, argv[0], dest_type, sm_id) < 0)\r
+                       IBERROR("can't resolve destination port %s", argv[0]);\r
+       } else {\r
+               if (ib_resolve_self(&portid, &port, 0) < 0)\r
+                       IBERROR("can't resolve self port %s", argv[0]);\r
+       }\r
+\r
+       if (ib_resolve_addr(&portid, port, show_lid, show_gid) < 0)\r
+               IBERROR("can't resolve requested address");\r
+       exit(0);\r
+}\r
diff --git a/branches/winverbs/tools/infiniband_diags/src/ibaddr/SOURCES b/branches/winverbs/tools/infiniband_diags/src/ibaddr/SOURCES
new file mode 100644 (file)
index 0000000..cbaf51c
--- /dev/null
@@ -0,0 +1,30 @@
+TARGETNAME = ibaddr\r
+TARGETPATH = ..\..\..\..\bin\user\obj$(BUILD_ALT_DIR)\r
+TARGETTYPE = PROGRAM\r
+\r
+UMTYPE = console\r
+UMENTRY = main\r
+\r
+USE_MSVCRT = 1\r
+USE_STL = 1\r
+USE_NATIVE_EH = 1\r
+USE_IOSTREAM = 1\r
+\r
+SOURCES = ..\ibaddr.c ..\ibdiag_common.c\r
+       \r
+INCLUDES = ..;..\..\include;..\..\..\..\ulp\libibmad\include;..\..\..\..\ulp\libibumad\include;..\..\..\..\inc;..\..\..\..\inc\user;\r
+\r
+TARGETLIBS =   \\r
+       $(SDK_LIB_PATH)\kernel32.lib    \\r
+       $(SDK_LIB_PATH)\advapi32.lib    \\r
+       $(SDK_LIB_PATH)\user32.lib      \\r
+       $(SDK_LIB_PATH)\ole32.lib       \\r
+       $(SDK_LIB_PATH)\ws2_32.lib      \\r
+!if $(FREEBUILD)\r
+       $(TARGETPATH)\*\libibmad.lib    \\r
+       $(TARGETPATH)\*\libibumad.lib   \r
+!else\r
+       $(TARGETPATH)\*\libibmadd.lib   \\r
+       $(TARGETPATH)\*\libibumadd.lib  \r
+!endif\r
+\r
diff --git a/branches/winverbs/tools/infiniband_diags/src/ibdiag_common.c b/branches/winverbs/tools/infiniband_diags/src/ibdiag_common.c
new file mode 100644 (file)
index 0000000..a78e4e1
--- /dev/null
@@ -0,0 +1,86 @@
+/*\r
+ * Copyright (c) 2006-2007 The Regents of the University of California.\r
+ * Copyright (c) 2004-2006 Voltaire, 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
+/**\r
+ * Define common functions which can be included in the various C based diags.\r
+ */\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+\r
+#if defined(_WIN32) || defined(_WIN64)\r
+#include <windows.h>\r
+#include <winsock2.h>\r
+#include <ws2tcpip.h>\r
+#if !defined(getpid)\r
+    #define getpid GetCurrentProcessId\r
+#endif\r
+#else\r
+#define _GNU_SOURCE\r
+#include <errno.h>\r
+#include <string.h>\r
+#include <stdarg.h>\r
+#include <sys/types.h>\r
+#include <unistd.h>\r
+#include <ctype.h>\r
+#include <config.h>\r
+#endif\r
+\r
+#include "ibdiag_common.h"\r
+\r
+int ibdebug;\r
+\r
+void\r
+iberror(const char *fn, char *msg, ...)\r
+{\r
+       char buf[512], *s;\r
+       va_list va;\r
+       int n;\r
+\r
+       va_start(va, msg);\r
+       n = vsprintf(buf, msg, va);\r
+       va_end(va);\r
+       buf[n] = 0;\r
+\r
+       if ((s = strrchr(argv0, '/')))\r
+               argv0 = s + 1;\r
+\r
+       if (ibdebug)\r
+               printf("%s: iberror: [pid %d] %s: failed: %s\n", argv0, getpid(), fn, buf);\r
+       else\r
+               printf("%s: iberror: failed: %s\n", argv0, buf);\r
+\r
+       exit(-1);\r
+}\r
+\r
diff --git a/branches/winverbs/tools/infiniband_diags/src/ibnetdiscover.c b/branches/winverbs/tools/infiniband_diags/src/ibnetdiscover.c
new file mode 100644 (file)
index 0000000..faf89ec
--- /dev/null
@@ -0,0 +1,1051 @@
+/*\r
+ * Copyright (c) 2004-2008 Voltaire Inc.  All rights reserved.\r
+ * Copyright (c) 2007 Xsigo Systems 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
+#if HAVE_CONFIG_H\r
+#  include <config.h>\r
+#endif /* HAVE_CONFIG_H */\r
+\r
+#define _GNU_SOURCE\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <unistd.h>\r
+#include <stdarg.h>\r
+#include <time.h>\r
+#include <string.h>\r
+#include <getopt.h>\r
+#include <errno.h>\r
+#include <inttypes.h>\r
+\r
+#include <infiniband/common.h>\r
+#include <infiniband/umad.h>\r
+#include <infiniband/mad.h>\r
+#include <infiniband/complib/cl_nodenamemap.h>\r
+\r
+#include "ibnetdiscover.h"\r
+#include "grouping.h"\r
+#include "ibdiag_common.h"\r
+\r
+static char *node_type_str[] = {\r
+       "???",\r
+       "ca",\r
+       "switch",\r
+       "router",\r
+       "iwarp rnic"\r
+};\r
+\r
+static char *linkwidth_str[] = {\r
+       "??",\r
+       "1x",\r
+       "4x",\r
+       "??",\r
+       "8x",\r
+       "??",\r
+       "??",\r
+       "??",\r
+       "12x"\r
+};\r
+\r
+static char *linkspeed_str[] = {\r
+       "???",\r
+       "SDR",\r
+       "DDR",\r
+       "???",\r
+       "QDR"\r
+};\r
+\r
+static int timeout = 2000;             /* ms */\r
+static int dumplevel = 0;\r
+static int verbose;\r
+static FILE *f;\r
+\r
+char *argv0 = "ibnetdiscover";\r
+\r
+static char *node_name_map_file = NULL;\r
+static nn_map_t *node_name_map = NULL;\r
+\r
+Node *nodesdist[MAXHOPS+1];     /* last is Ca list */\r
+Node *mynode;\r
+int maxhops_discovered = 0;\r
+\r
+struct ChassisList *chassis = NULL;\r
+\r
+static char *\r
+get_linkwidth_str(int linkwidth)\r
+{\r
+       if (linkwidth > 8)\r
+               return linkwidth_str[0];\r
+       else\r
+               return linkwidth_str[linkwidth];\r
+}\r
+\r
+static char *\r
+get_linkspeed_str(int linkspeed)\r
+{\r
+       if (linkspeed > 4)\r
+               return linkspeed_str[0];\r
+       else\r
+               return linkspeed_str[linkspeed];\r
+}\r
+\r
+static inline const char*\r
+node_type_str2(Node *node)\r
+{\r
+       switch(node->type) {\r
+       case SWITCH_NODE: return "SW";\r
+       case CA_NODE:     return "CA";\r
+       case ROUTER_NODE: return "RT";\r
+       }\r
+       return "??";\r
+}\r
+\r
+void\r
+decode_port_info(void *pi, Port *port)\r
+{\r
+       mad_decode_field(pi, IB_PORT_LID_F, &port->lid);\r
+       mad_decode_field(pi, IB_PORT_LMC_F, &port->lmc);\r
+       mad_decode_field(pi, IB_PORT_STATE_F, &port->state);\r
+       mad_decode_field(pi, IB_PORT_PHYS_STATE_F, &port->physstate);\r
+       mad_decode_field(pi, IB_PORT_LINK_WIDTH_ACTIVE_F, &port->linkwidth);\r
+       mad_decode_field(pi, IB_PORT_LINK_SPEED_ACTIVE_F, &port->linkspeed);\r
+}\r
+\r
+\r
+int\r
+get_port(Port *port, int portnum, ib_portid_t *portid)\r
+{\r
+       char portinfo[64];\r
+       void *pi = portinfo;\r
+\r
+       port->portnum = portnum;\r
+\r
+       if (!smp_query(pi, portid, IB_ATTR_PORT_INFO, portnum, timeout))\r
+               return -1;\r
+       decode_port_info(pi, port);\r
+\r
+       DEBUG("portid %s portnum %d: lid %d state %d physstate %d %s %s",\r
+               portid2str(portid), portnum, port->lid, port->state, port->physstate, get_linkwidth_str(port->linkwidth), get_linkspeed_str(port->linkspeed));\r
+       return 1;\r
+}\r
+/*\r
+ * Returns 0 if non switch node is found, 1 if switch is found, -1 if error.\r
+ */\r
+int\r
+get_node(Node *node, Port *port, ib_portid_t *portid)\r
+{\r
+       char portinfo[64];\r
+       char switchinfo[64];\r
+       void *pi = portinfo, *ni = node->nodeinfo, *nd = node->nodedesc;\r
+       void *si = switchinfo;\r
+\r
+       if (!smp_query(ni, portid, IB_ATTR_NODE_INFO, 0, timeout))\r
+               return -1;\r
+\r
+       mad_decode_field(ni, IB_NODE_GUID_F, &node->nodeguid);\r
+       mad_decode_field(ni, IB_NODE_TYPE_F, &node->type);\r
+       mad_decode_field(ni, IB_NODE_NPORTS_F, &node->numports);\r
+       mad_decode_field(ni, IB_NODE_DEVID_F, &node->devid);\r
+       mad_decode_field(ni, IB_NODE_VENDORID_F, &node->vendid);\r
+       mad_decode_field(ni, IB_NODE_SYSTEM_GUID_F, &node->sysimgguid);\r
+       mad_decode_field(ni, IB_NODE_PORT_GUID_F, &node->portguid);\r
+       mad_decode_field(ni, IB_NODE_LOCAL_PORT_F, &node->localport);\r
+       port->portnum = node->localport;\r
+       port->portguid = node->portguid;\r
+\r
+       if (!smp_query(nd, portid, IB_ATTR_NODE_DESC, 0, timeout))\r
+               return -1;\r
+\r
+       if (!smp_query(pi, portid, IB_ATTR_PORT_INFO, 0, timeout))\r
+               return -1;\r
+       decode_port_info(pi, port);\r
+\r
+       if (node->type != SWITCH_NODE)\r
+               return 0;\r
+\r
+       node->smalid = port->lid;\r
+       node->smalmc = port->lmc;\r
+\r
+       /* after we have the sma information find out the real PortInfo for this port */\r
+       if (!smp_query(pi, portid, IB_ATTR_PORT_INFO, node->localport, timeout))\r
+               return -1;\r
+       decode_port_info(pi, port);\r
+\r
+        if (!smp_query(si, portid, IB_ATTR_SWITCH_INFO, 0, timeout))\r
+                node->smaenhsp0 = 0;   /* assume base SP0 */\r
+       else\r
+               mad_decode_field(si, IB_SW_ENHANCED_PORT0_F, &node->smaenhsp0);\r
+\r
+       DEBUG("portid %s: got switch node %" PRIx64 " '%s'",\r
+             portid2str(portid), node->nodeguid, node->nodedesc);\r
+       return 1;\r
+}\r
+\r
+static int\r
+extend_dpath(ib_dr_path_t *path, int nextport)\r
+{\r
+       if (path->cnt+2 >= sizeof(path->p))\r
+               return -1;\r
+       ++path->cnt;\r
+       if (path->cnt > maxhops_discovered)\r
+               maxhops_discovered = path->cnt;\r
+       path->p[path->cnt] = nextport;\r
+       return path->cnt;\r
+}\r
+\r
+static void\r
+dump_endnode(ib_portid_t *path, char *prompt, Node *node, Port *port)\r
+{\r
+       if (!dumplevel)\r
+               return;\r
+\r
+       fprintf(f, "%s -> %s %s {%016" PRIx64 "} portnum %d lid %d-%d\"%s\"\n",\r
+               portid2str(path), prompt,\r
+               (node->type <= IB_NODE_MAX ? node_type_str[node->type] : "???"),\r
+               node->nodeguid, node->type == SWITCH_NODE ? 0 : port->portnum,\r
+               port->lid, port->lid + (1 << port->lmc) - 1,\r
+               clean_nodedesc(node->nodedesc));\r
+}\r
+\r
+#define HASHGUID(guid)         ((uint32_t)(((uint32_t)(guid) * 101) ^ ((uint32_t)((guid) >> 32) * 103)))\r
+#define HTSZ 137\r
+\r
+static Node *nodestbl[HTSZ];\r
+\r
+static Node *\r
+find_node(Node *new)\r
+{\r
+       int hash = HASHGUID(new->nodeguid) % HTSZ;\r
+       Node *node;\r
+\r
+       for (node = nodestbl[hash]; node; node = node->htnext)\r
+               if (node->nodeguid == new->nodeguid)\r
+                       return node;\r
+\r
+       return NULL;\r
+}\r
+\r
+static Node *\r
+create_node(Node *temp, ib_portid_t *path, int dist)\r
+{\r
+       Node *node;\r
+       int hash = HASHGUID(temp->nodeguid) % HTSZ;\r
+\r
+       node = malloc(sizeof(*node));\r
+       if (!node)\r
+               return NULL;\r
+\r
+       memcpy(node, temp, sizeof(*node));\r
+       node->dist = dist;\r
+       node->path = *path;\r
+\r
+       node->htnext = nodestbl[hash];\r
+       nodestbl[hash] = node;\r
+\r
+       if (node->type != SWITCH_NODE)\r
+               dist = MAXHOPS;         /* special Ca list */\r
+\r
+       node->dnext = nodesdist[dist];\r
+       nodesdist[dist] = node;\r
+\r
+       return node;\r
+}\r
+\r
+static Port *\r
+find_port(Node *node, Port *port)\r
+{\r
+       Port *old;\r
+\r
+       for (old = node->ports; old; old = old->next)\r
+               if (old->portnum == port->portnum)\r
+                       return old;\r
+\r
+       return NULL;\r
+}\r
+\r
+static Port *\r
+create_port(Node *node, Port *temp)\r
+{\r
+       Port *port;\r
+\r
+       port = malloc(sizeof(*port));\r
+       if (!port)\r
+               return NULL;\r
+\r
+       memcpy(port, temp, sizeof(*port));\r
+       port->node = node;\r
+       port->next = node->ports;\r
+       node->ports = port;\r
+\r
+       return port;\r
+}\r
+\r
+static void\r
+link_ports(Node *node, Port *port, Node *remotenode, Port *remoteport)\r
+{\r
+       DEBUG("linking: 0x%" PRIx64 " %p->%p:%u and 0x%" PRIx64 " %p->%p:%u",\r
+               node->nodeguid, node, port, port->portnum,\r
+               remotenode->nodeguid, remotenode, remoteport, remoteport->portnum);\r
+       if (port->remoteport)\r
+               port->remoteport->remoteport = NULL;\r
+       if (remoteport->remoteport)\r
+               remoteport->remoteport->remoteport = NULL;\r
+       port->remoteport = remoteport;\r
+       remoteport->remoteport = port;\r
+}\r
+\r
+static int\r
+handle_port(Node *node, Port *port, ib_portid_t *path, int portnum, int dist)\r
+{\r
+       Node node_buf;\r
+       Port port_buf;\r
+       Node *remotenode, *oldnode;\r
+       Port *remoteport, *oldport;\r
+\r
+       memset(&node_buf, 0, sizeof(node_buf));\r
+       memset(&port_buf, 0, sizeof(port_buf));\r
+\r
+       DEBUG("handle node %p port %p:%d dist %d", node, port, portnum, dist);\r
+       if (port->physstate != 5)       /* LinkUp */\r
+               return -1;\r
+\r
+       if (extend_dpath(&path->drpath, portnum) < 0)\r
+               return -1;\r
+\r
+       if (get_node(&node_buf, &port_buf, path) < 0) {\r
+               IBWARN("NodeInfo on %s failed, skipping port",\r
+                       portid2str(path));\r
+               path->drpath.cnt--;     /* restore path */\r
+               return -1;\r
+       }\r
+\r
+       oldnode = find_node(&node_buf);\r
+       if (oldnode)\r
+               remotenode = oldnode;\r
+       else if (!(remotenode = create_node(&node_buf, path, dist + 1)))\r
+               IBERROR("no memory");\r
+\r
+       oldport = find_port(remotenode, &port_buf);\r
+       if (oldport) {\r
+               remoteport = oldport;\r
+               if (node != remotenode || port != remoteport)\r
+                       IBWARN("port moving...");\r
+       } else if (!(remoteport = create_port(remotenode, &port_buf)))\r
+               IBERROR("no memory");\r
+\r
+       dump_endnode(path, oldnode ? "known remote" : "new remote",\r
+                    remotenode, remoteport);\r
+\r
+       link_ports(node, port, remotenode, remoteport);\r
+\r
+       path->drpath.cnt--;     /* restore path */\r
+       return 0;\r
+}\r
+\r
+/*\r
+ * Return 1 if found, 0 if not, -1 on errors.\r
+ */\r
+static int\r
+discover(ib_portid_t *from)\r
+{\r
+       Node node_buf;\r
+       Port port_buf;\r
+       Node *node;\r
+       Port *port;\r
+       int i;\r
+       int dist = 0;\r
+       ib_portid_t *path;\r
+\r
+       DEBUG("from %s", portid2str(from));\r
+\r
+       memset(&node_buf, 0, sizeof(node_buf));\r
+       memset(&port_buf, 0, sizeof(port_buf));\r
+\r
+       if (get_node(&node_buf, &port_buf, from) < 0) {\r
+               IBWARN("can't reach node %s", portid2str(from));\r
+               return -1;\r
+       }\r
+\r
+       node = create_node(&node_buf, from, 0);\r
+       if (!node)\r
+               IBERROR("out of memory");\r
+\r
+       mynode = node;\r
+\r
+       port = create_port(node, &port_buf);\r
+       if (!port)\r
+               IBERROR("out of memory");\r
+\r
+       if (node->type != SWITCH_NODE &&\r
+           handle_port(node, port, from, node->localport, 0) < 0)\r
+               return 0;\r
+\r
+       for (dist = 0; dist < MAXHOPS; dist++) {\r
+\r
+               for (node = nodesdist[dist]; node; node = node->dnext) {\r
+\r
+                       path = &node->path;\r
+\r
+                       DEBUG("dist %d node %p", dist, node);\r
+                       dump_endnode(path, "processing", node, port);\r
+\r
+                       for (i = 1; i <= node->numports; i++) {\r
+                               if (i == node->localport)\r
+                                       continue;\r
+\r
+                               if (get_port(&port_buf, i, path) < 0) {\r
+                                       IBWARN("can't reach node %s port %d", portid2str(path), i);\r
+                                       continue;\r
+                               }\r
+\r
+                               port = find_port(node, &port_buf);\r
+                               if (port)\r
+                                       continue;\r
+\r
+                               port = create_port(node, &port_buf);\r
+                               if (!port)\r
+                                       IBERROR("out of memory");\r
+\r
+                               /* If switch, set port GUID to node GUID */\r
+                               if (node->type == SWITCH_NODE)\r
+                                       port->portguid = node->portguid;\r
+\r
+                               handle_port(node, port, path, i, dist);\r
+                       }\r
+               }\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+char *\r
+node_name(Node *node)\r
+{\r
+       static char buf[256];\r
+\r
+       switch(node->type) {\r
+       case SWITCH_NODE:\r
+               sprintf(buf, "\"%s", "S");\r
+               break;\r
+       case CA_NODE:\r
+               sprintf(buf, "\"%s", "H");\r
+               break;\r
+       case ROUTER_NODE:\r
+               sprintf(buf, "\"%s", "R");\r
+               break;\r
+       default:\r
+               sprintf(buf, "\"%s", "?");\r
+               break;\r
+       }\r
+       sprintf(buf+2, "-%016" PRIx64 "\"", node->nodeguid);\r
+\r
+       return buf;\r
+}\r
+\r
+void\r
+list_node(Node *node)\r
+{\r
+       char *node_type;\r
+       char *nodename = remap_node_name(node_name_map, node->nodeguid,\r
+                                             node->nodedesc);\r
+\r
+       switch(node->type) {\r
+       case SWITCH_NODE:\r
+               node_type = "Switch";\r
+               break;\r
+       case CA_NODE:\r
+               node_type = "Ca";\r
+               break;\r
+       case ROUTER_NODE:\r
+               node_type = "Router";\r
+               break;\r
+       default:\r
+               node_type = "???";\r
+               break;\r
+       }\r
+       fprintf(f, "%s\t : 0x%016" PRIx64 " ports %d devid 0x%x vendid 0x%x \"%s\"\n",\r
+               node_type,\r
+               node->nodeguid, node->numports, node->devid, node->vendid,\r
+               nodename);\r
+\r
+       free(nodename);\r
+}\r
+\r
+void\r
+out_ids(Node *node, int group, char *chname)\r
+{\r
+       fprintf(f, "\nvendid=0x%x\ndevid=0x%x\n", node->vendid, node->devid);\r
+       if (node->sysimgguid)\r
+               fprintf(f, "sysimgguid=0x%" PRIx64, node->sysimgguid);\r
+       if (group\r
+           && node->chrecord && node->chrecord->chassisnum) {\r
+               fprintf(f, "\t\t# Chassis %d", node->chrecord->chassisnum);\r
+               if (chname)\r
+                       fprintf(f, " (%s)", chname);\r
+               if (is_xsigo_tca(node->nodeguid) && node->ports->remoteport)\r
+                       fprintf(f, " slot %d", node->ports->remoteport->portnum);\r
+       }\r
+       fprintf(f, "\n");\r
+}\r
+\r
+uint64_t\r
+out_chassis(int chassisnum)\r
+{\r
+       uint64_t guid;\r
+\r
+       fprintf(f, "\nChassis %d", chassisnum);\r
+       guid = get_chassis_guid(chassisnum);\r
+       if (guid)\r
+               fprintf(f, " (guid 0x%" PRIx64 ")", guid);\r
+       fprintf(f, "\n");\r
+       return guid;\r
+}\r
+\r
+void\r
+out_switch(Node *node, int group, char *chname)\r
+{\r
+       char *str;\r
+       char *nodename = NULL;\r
+\r
+       out_ids(node, group, chname);\r
+       fprintf(f, "switchguid=0x%" PRIx64, node->nodeguid);\r
+       fprintf(f, "(%" PRIx64 ")", node->portguid);\r
+       /* Currently, only if Voltaire chassis */\r
+       if (group\r
+           && node->chrecord && node->chrecord->chassisnum\r
+           && node->vendid == VTR_VENDOR_ID) {\r
+               str = get_chassis_type(node->chrecord->chassistype);\r
+               if (str)\r
+                       fprintf(f, "%s ", str);\r
+               str = get_chassis_slot(node->chrecord->chassisslot);\r
+               if (str)\r
+                       fprintf(f, "%s ", str);\r
+               fprintf(f, "%d Chip %d", node->chrecord->slotnum, node->chrecord->anafanum);\r
+       }\r
+\r
+       nodename = remap_node_name(node_name_map, node->nodeguid,\r
+                               node->nodedesc);\r
+\r
+       fprintf(f, "\nSwitch\t%d %s\t\t# \"%s\" %s port 0 lid %d lmc %d\n",\r
+               node->numports, node_name(node),\r
+               nodename,\r
+               node->smaenhsp0 ? "enhanced" : "base",\r
+               node->smalid, node->smalmc);\r
+\r
+       free(nodename);\r
+}\r
+\r
+void\r
+out_ca(Node *node, int group, char *chname)\r
+{\r
+       char *node_type;\r
+       char *node_type2;\r
+       char *nodename = remap_node_name(node_name_map, node->nodeguid,\r
+                                             node->nodedesc);\r
+\r
+       out_ids(node, group, chname);\r
+       switch(node->type) {\r
+       case CA_NODE:\r
+               node_type = "ca";\r
+               node_type2 = "Ca";\r
+               break;\r
+       case ROUTER_NODE:\r
+               node_type = "rt";\r
+               node_type2 = "Rt";\r
+               break;\r
+       default:\r
+               node_type = "???";\r
+               node_type2 = "???";\r
+               break;\r
+       }\r
+\r
+       fprintf(f, "%sguid=0x%" PRIx64 "\n", node_type, node->nodeguid);\r
+       fprintf(f, "%s\t%d %s\t\t# \"%s\"",\r
+               node_type2, node->numports, node_name(node),\r
+               nodename);\r
+       if (group && is_xsigo_hca(node->nodeguid))\r
+               fprintf(f, " (scp)");\r
+       fprintf(f, "\n");\r
+\r
+       free(nodename);\r
+}\r
+\r
+static char *\r
+out_ext_port(Port *port, int group)\r
+{\r
+       char *str = NULL;\r
+\r
+       /* Currently, only if Voltaire chassis */\r
+       if (group\r
+           && port->node->chrecord && port->node->vendid == VTR_VENDOR_ID)\r
+               str = portmapstring(port);\r
+\r
+       return (str);\r
+}\r
+\r
+void\r
+out_switch_port(Port *port, int group)\r
+{\r
+       char *ext_port_str = NULL;\r
+       char *rem_nodename = NULL;\r
+\r
+       DEBUG("port %p:%d remoteport %p", port, port->portnum, port->remoteport);\r
+       fprintf(f, "[%d]", port->portnum);\r
+\r
+       ext_port_str = out_ext_port(port, group);\r
+       if (ext_port_str)\r
+               fprintf(f, "%s", ext_port_str);\r
+\r
+       rem_nodename = remap_node_name(node_name_map,\r
+                               port->remoteport->node->nodeguid,\r
+                               port->remoteport->node->nodedesc);\r
+\r
+       ext_port_str = out_ext_port(port->remoteport, group);\r
+       fprintf(f, "\t%s[%d]%s",\r
+               node_name(port->remoteport->node),\r
+               port->remoteport->portnum,\r
+               ext_port_str ? ext_port_str : "");\r
+       if (port->remoteport->node->type != SWITCH_NODE)\r
+               fprintf(f, "(%" PRIx64 ") ", port->remoteport->portguid);\r
+       fprintf(f, "\t\t# \"%s\" lid %d %s%s",\r
+               rem_nodename,\r
+               port->remoteport->node->type == SWITCH_NODE ? port->remoteport->node->smalid : port->remoteport->lid,\r
+               get_linkwidth_str(port->linkwidth),\r
+               get_linkspeed_str(port->linkspeed));\r
+\r
+       if (is_xsigo_tca(port->remoteport->portguid))\r
+               fprintf(f, " slot %d", port->portnum);\r
+       else if (is_xsigo_hca(port->remoteport->portguid))\r
+               fprintf(f, " (scp)");\r
+       fprintf(f, "\n");\r
+\r
+       free(rem_nodename);\r
+}\r
+\r
+void\r
+out_ca_port(Port *port, int group)\r
+{\r
+       char *str = NULL;\r
+       char *rem_nodename = NULL;\r
+\r
+       fprintf(f, "[%d]", port->portnum);\r
+       if (port->node->type != SWITCH_NODE)\r
+               fprintf(f, "(%" PRIx64 ") ", port->portguid);\r
+       fprintf(f, "\t%s[%d]",\r
+               node_name(port->remoteport->node),\r
+               port->remoteport->portnum);\r
+       str = out_ext_port(port->remoteport, group);\r
+       if (str)\r
+               fprintf(f, "%s", str);\r
+       if (port->remoteport->node->type != SWITCH_NODE)\r
+               fprintf(f, " (%" PRIx64 ") ", port->remoteport->portguid);\r
+\r
+       rem_nodename = remap_node_name(node_name_map,\r
+                               port->remoteport->node->nodeguid,\r
+                               port->remoteport->node->nodedesc);\r
+\r
+       fprintf(f, "\t\t# lid %d lmc %d \"%s\" lid %d %s%s\n",\r
+               port->lid, port->lmc, rem_nodename,\r
+               port->remoteport->node->type == SWITCH_NODE ? port->remoteport->node->smalid : port->remoteport->lid,\r
+               get_linkwidth_str(port->linkwidth),\r
+               get_linkspeed_str(port->linkspeed));\r
+\r
+       free(rem_nodename);\r
+}\r
+\r
+int\r
+dump_topology(int listtype, int group)\r
+{\r
+       Node *node;\r
+       Port *port;\r
+       int i = 0, dist = 0;\r
+       time_t t = time(0);\r
+       uint64_t chguid;\r
+       char *chname = NULL;\r
+\r
+       if (!listtype) {\r
+               fprintf(f, "#\n# Topology file: generated on %s#\n", ctime(&t));\r
+               fprintf(f, "# Max of %d hops discovered\n", maxhops_discovered);\r
+               fprintf(f, "# Initiated from node %016" PRIx64 " port %016" PRIx64 "\n", mynode->nodeguid, mynode->portguid);\r
+       }\r
+\r
+       /* Make pass on switches */\r
+       if (group && !listtype) {\r
+               ChassisList *ch = NULL;\r
+\r
+               /* Chassis based switches first */\r
+               for (ch = chassis; ch; ch = ch->next) {\r
+                       int n = 0;\r
+\r
+                       if (!ch->chassisnum)\r
+                               continue;\r
+                       chguid = out_chassis(ch->chassisnum);\r
+                       if (chname)\r
+                               free(chname);\r
+                       chname = NULL;\r
+                       if (is_xsigo_guid(chguid)) {\r
+                               for (node = nodesdist[MAXHOPS]; node; node = node->dnext) {\r
+                                       if (!node->chrecord ||\r
+                                           !node->chrecord->chassisnum)\r
+                                               continue;\r
+\r
+                                       if (node->chrecord->chassisnum != ch->chassisnum)\r
+                                               continue;\r
+\r
+                                       if (is_xsigo_hca(node->nodeguid)) {\r
+                                               chname = remap_node_name(node_name_map,\r
+                                                               node->nodeguid,\r
+                                                               node->nodedesc);\r
+                                               fprintf(f, "Hostname: %s\n", chname);\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+                       fprintf(f, "\n# Spine Nodes");\r
+                       for (n = 1; n <= (SPINES_MAX_NUM+1); n++) {\r
+                               if (ch->spinenode[n]) {\r
+                                       out_switch(ch->spinenode[n], group, chname);\r
+                                       for (port = ch->spinenode[n]->ports; port; port = port->next, i++)\r
+                                               if (port->remoteport)\r
+                                                       out_switch_port(port, group);\r
+                               }\r
+                       }\r
+                       fprintf(f, "\n# Line Nodes");\r
+                       for (n = 1; n <= (LINES_MAX_NUM+1); n++) {\r
+                               if (ch->linenode[n]) {\r
+                                       out_switch(ch->linenode[n], group, chname);\r
+                                       for (port = ch->linenode[n]->ports; port; port = port->next, i++)\r
+                                               if (port->remoteport)\r
+                                                       out_switch_port(port, group);\r
+                               }\r
+                       }\r
+\r
+                       fprintf(f, "\n# Chassis Switches");\r
+                       for (dist = 0; dist <= maxhops_discovered; dist++) {\r
+\r
+                               for (node = nodesdist[dist]; node; node = node->dnext) {\r
+\r
+                                       /* Non Voltaire chassis */\r
+                                       if (node->vendid == VTR_VENDOR_ID)\r
+                                               continue;\r
+                                       if (!node->chrecord ||\r
+                                           !node->chrecord->chassisnum)\r
+                                               continue;\r
+\r
+                                       if (node->chrecord->chassisnum != ch->chassisnum)\r
+                                               continue;\r
+\r
+                                       out_switch(node, group, chname);\r
+                                       for (port = node->ports; port; port = port->next, i++)\r
+                                               if (port->remoteport)\r
+                                                       out_switch_port(port, group);\r
+\r
+                               }\r
+\r
+                       }\r
+\r
+                       fprintf(f, "\n# Chassis CAs");\r
+                       for (node = nodesdist[MAXHOPS]; node; node = node->dnext) {\r
+                               if (!node->chrecord ||\r
+                                   !node->chrecord->chassisnum)\r
+                                       continue;\r
+\r
+                               if (node->chrecord->chassisnum != ch->chassisnum)\r
+                                       continue;\r
+\r
+                               out_ca(node, group, chname);\r
+                               for (port = node->ports; port; port = port->next, i++)\r
+                                       if (port->remoteport)\r
+                                               out_ca_port(port, group);\r
+\r
+                       }\r
+\r
+               }\r
+\r
+       } else {\r
+               for (dist = 0; dist <= maxhops_discovered; dist++) {\r
+\r
+                       for (node = nodesdist[dist]; node; node = node->dnext) {\r
+\r
+                               DEBUG("SWITCH: dist %d node %p", dist, node);\r
+                               if (!listtype)\r
+                                       out_switch(node, group, chname);\r
+                               else {\r
+                                       if (listtype & LIST_SWITCH_NODE)\r
+                                               list_node(node);\r
+                                       continue;\r
+                               }\r
+\r
+                               for (port = node->ports; port; port = port->next, i++)\r
+                                       if (port->remoteport)\r
+                                               out_switch_port(port, group);\r
+                       }\r
+               }\r
+       }\r
+\r
+       if (chname)\r
+               free(chname);\r
+       chname = NULL;\r
+       if (group && !listtype) {\r
+\r
+               fprintf(f, "\nNon-Chassis Nodes\n");\r
+\r
+               for (dist = 0; dist <= maxhops_discovered; dist++) {\r
+\r
+                       for (node = nodesdist[dist]; node; node = node->dnext) {\r
+\r
+                               DEBUG("SWITCH: dist %d node %p", dist, node);\r
+                               /* Now, skip chassis based switches */\r
+                               if (node->chrecord &&\r
+                                   node->chrecord->chassisnum)\r
+                                       continue;\r
+                               out_switch(node, group, chname);\r
+\r
+                               for (port = node->ports; port; port = port->next, i++)\r
+                                       if (port->remoteport)\r
+                                               out_switch_port(port, group);\r
+                       }\r
+\r
+               }\r
+\r
+       }\r
+\r
+       /* Make pass on CAs */\r
+       for (node = nodesdist[MAXHOPS]; node; node = node->dnext) {\r
+\r
+               DEBUG("CA: dist %d node %p", dist, node);\r
+               if (!listtype) {\r
+                       /* Now, skip chassis based CAs */\r
+                       if (group && node->chrecord &&\r
+                           node->chrecord->chassisnum)\r
+                               continue;\r
+                       out_ca(node, group, chname);\r
+               } else {\r
+                       if (((listtype & LIST_CA_NODE) && (node->type == CA_NODE)) ||\r
+                           ((listtype & LIST_ROUTER_NODE) && (node->type == ROUTER_NODE)))\r
+                               list_node(node);\r
+                       continue;\r
+               }\r
+\r
+               for (port = node->ports; port; port = port->next, i++)\r
+                       if (port->remoteport)\r
+                               out_ca_port(port, group);\r
+       }\r
+\r
+       if (chname)\r
+               free(chname);\r
+\r
+       return i;\r
+}\r
+\r
+void dump_ports_report ()\r
+{\r
+       int b, n = 0, p;\r
+       Node *node;\r
+       Port *port;\r
+\r
+       // If switch and LID == 0, search of other switch ports with\r
+       // valid LID and assign it to all ports of that switch\r
+       for (b = 0; b <= MAXHOPS; b++)\r
+               for (node = nodesdist[b]; node; node = node->dnext)\r
+                       if (node->type == SWITCH_NODE) {\r
+                               int swlid = 0;\r
+                               for (p = 0, port = node->ports;\r
+                                    p < node->numports && port && !swlid;\r
+                                    port = port->next)\r
+                                       if (port->lid != 0)\r
+                                               swlid = port->lid;\r
+                               for (p = 0, port = node->ports;\r
+                                    p < node->numports && port;\r
+                                    port = port->next)\r
+                                       port->lid = swlid;\r
+                       }\r
+\r
+       for (b = 0; b <= MAXHOPS; b++)\r
+               for (node = nodesdist[b]; node; node = node->dnext) {\r
+                       for (p = 0, port = node->ports;\r
+                            p < node->numports && port;\r
+                            p++, port = port->next) {\r
+                               fprintf(stdout,\r
+                                       "%2s %5d %2d 0x%016" PRIx64 " %s %s",\r
+                                       node_type_str2(port->node), port->lid,\r
+                                       port->portnum,\r
+                                       port->portguid,\r
+                                       get_linkwidth_str(port->linkwidth),\r
+                                       get_linkspeed_str(port->linkspeed));\r
+                               if (port->remoteport)\r
+                                       fprintf(stdout,\r
+                                               " - %2s %5d %2d 0x%016" PRIx64\r
+                                               " ( '%s' - '%s' )\n",\r
+                                               node_type_str2(port->remoteport->node),\r
+                                               port->remoteport->lid,\r
+                                               port->remoteport->portnum,\r
+                                               port->remoteport->portguid,\r
+                                               port->node->nodedesc,\r
+                                               port->remoteport->node->nodedesc);\r
+                               else\r
+                                       fprintf(stdout, "%36s'%s'\n", "",\r
+                                               port->node->nodedesc);\r
+                       }\r
+                       n++;\r
+               }\r
+}\r
+\r
+void\r
+usage(void)\r
+{\r
+       fprintf(stderr, "Usage: %s [-d(ebug)] -e(rr_show) -v(erbose) -s(how) -l(ist) -g(rouping) -H(ca_list) -S(witch_list) -R(outer_list) -V(ersion) -C ca_name -P ca_port "\r
+                       "-t(imeout) timeout_ms --node-name-map node-name-map] -p(orts) [<topology-file>]\n",\r
+                       argv0);\r
+       fprintf(stderr, "       --node-name-map <node-name-map> specify a node name map file\n");\r
+       exit(-1);\r
+}\r
+\r
+int\r
+main(int argc, char **argv)\r
+{\r
+       int mgmt_classes[2] = {IB_SMI_CLASS, IB_SMI_DIRECT_CLASS};\r
+       ib_portid_t my_portid = {0};\r
+       int udebug = 0, list = 0;\r
+       char *ca = 0;\r
+       int ca_port = 0;\r
+       int group = 0;\r
+       int ports_report = 0;\r
+\r
+       static char const str_opts[] = "C:P:t:devslgHSRpVhu";\r
+       static const struct option long_opts[] = {\r
+               { "C", 1, 0, 'C'},\r
+               { "P", 1, 0, 'P'},\r
+               { "debug", 0, 0, 'd'},\r
+               { "err_show", 0, 0, 'e'},\r
+               { "verbose", 0, 0, 'v'},\r
+               { "show", 0, 0, 's'},\r
+               { "list", 0, 0, 'l'},\r
+               { "grouping", 0, 0, 'g'},\r
+               { "Hca_list", 0, 0, 'H'},\r
+               { "Switch_list", 0, 0, 'S'},\r
+               { "Router_list", 0, 0, 'R'},\r
+               { "timeout", 1, 0, 't'},\r
+               { "node-name-map", 1, 0, 1},\r
+               { "ports", 0, 0, 'p'},\r
+               { "Version", 0, 0, 'V'},\r
+               { "help", 0, 0, 'h'},\r
+               { "usage", 0, 0, 'u'},\r
+               { }\r
+       };\r
+\r
+       f = stdout;\r
+\r
+       argv0 = argv[0];\r
+\r
+       while (1) {\r
+               int ch = getopt_long(argc, argv, str_opts, long_opts, NULL);\r
+               if ( ch == -1 )\r
+                       break;\r
+               switch(ch) {\r
+               case 1:\r
+                       node_name_map_file = strdup(optarg);\r
+                       break;\r
+               case 'C':\r
+                       ca = optarg;\r
+                       break;\r
+               case 'P':\r
+                       ca_port = strtoul(optarg, 0, 0);\r
+                       break;\r
+               case 'd':\r
+                       ibdebug++;\r
+                       madrpc_show_errors(1);\r
+                       umad_debug(udebug);\r
+                       udebug++;\r
+                       break;\r
+               case 't':\r
+                       timeout = strtoul(optarg, 0, 0);\r
+                       break;\r
+               case 'v':\r
+                       verbose++;\r
+                       dumplevel++;\r
+                       break;\r
+               case 's':\r
+                       dumplevel = 1;\r
+                       break;\r
+               case 'e':\r
+                       madrpc_show_errors(1);\r
+                       break;\r
+               case 'l':\r
+                       list = LIST_CA_NODE | LIST_SWITCH_NODE | LIST_ROUTER_NODE;\r
+                       break;\r
+               case 'g':\r
+                       group = 1;\r
+                       break;\r
+               case 'S':\r
+                       list = LIST_SWITCH_NODE;\r
+                       break;\r
+               case 'H':\r
+                       list = LIST_CA_NODE;\r
+                       break;\r
+               case 'R':\r
+                       list = LIST_ROUTER_NODE;\r
+                       break;\r
+               case 'V':\r
+                       fprintf(stderr, "%s %s\n", argv0, get_build_version() );\r
+                       exit(-1);\r
+               case 'p':\r
+                       ports_report = 1;\r
+                       break;\r
+               default:\r
+                       usage();\r
+                       break;\r
+               }\r
+       }\r
+       argc -= optind;\r
+       argv += optind;\r
+\r
+       if (argc && !(f = fopen(argv[0], "w")))\r
+               IBERROR("can't open file %s for writing", argv[0]);\r
+\r
+       madrpc_init(ca, ca_port, mgmt_classes, 2);\r
+       node_name_map = open_node_name_map(node_name_map_file);\r
+\r
+       if (discover(&my_portid) < 0)\r
+               IBERROR("discover");\r
+\r
+       if (group)\r
+               chassis = group_nodes();\r
+\r
+       if (ports_report)\r
+               dump_ports_report();\r
+       else\r
+               dump_topology(list, group);\r
+\r
+       close_node_name_map(node_name_map);\r
+       exit(0);\r
+}\r
diff --git a/branches/winverbs/tools/infiniband_diags/src/ibnetdiscover/SOURCES b/branches/winverbs/tools/infiniband_diags/src/ibnetdiscover/SOURCES
new file mode 100644 (file)
index 0000000..849db8e
--- /dev/null
@@ -0,0 +1,30 @@
+TARGETNAME = ibnetdiscover\r
+TARGETPATH = ..\..\..\..\bin\user\obj$(BUILD_ALT_DIR)\r
+TARGETTYPE = PROGRAM\r
+\r
+UMTYPE = console\r
+UMENTRY = main\r
+\r
+USE_MSVCRT = 1\r
+USE_STL = 1\r
+USE_NATIVE_EH = 1\r
+USE_IOSTREAM = 1\r
+\r
+SOURCES = ..\ibnetdiscover.c ..\ibdiag_common.c\r
+       \r
+INCLUDES = ..;..\..\include;..\..\..\..\ulp\libibmad\include;..\..\..\..\ulp\libibumad\include;..\..\..\..\inc;..\..\..\..\inc\user;\r
+\r
+TARGETLIBS =   \\r
+       $(SDK_LIB_PATH)\kernel32.lib    \\r
+       $(SDK_LIB_PATH)\advapi32.lib    \\r
+       $(SDK_LIB_PATH)\user32.lib      \\r
+       $(SDK_LIB_PATH)\ole32.lib       \\r
+       $(SDK_LIB_PATH)\ws2_32.lib      \\r
+!if $(FREEBUILD)\r
+       $(TARGETPATH)\*\libibmad.lib    \\r
+       $(TARGETPATH)\*\libibumad.lib   \r
+!else\r
+       $(TARGETPATH)\*\libibmadd.lib   \\r
+       $(TARGETPATH)\*\libibumadd.lib  \r
+!endif\r
+\r
diff --git a/branches/winverbs/tools/infiniband_diags/src/ibping.c b/branches/winverbs/tools/infiniband_diags/src/ibping.c
new file mode 100644 (file)
index 0000000..767436b
--- /dev/null
@@ -0,0 +1,338 @@
+/*\r
+ * Copyright (c) 2004-2008 Voltaire 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
+#if HAVE_CONFIG_H\r
+#  include <config.h>\r
+#endif /* HAVE_CONFIG_H */\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+\r
+#if defined(_WIN32) \r
+#include <windows.h>\r
+#include <winsock2.h>\r
+#include <ws2tcpip.h> \r
+#include "..\..\..\..\etc\user\getopt.c"\r
+#else\r
+#include <unistd.h>\r
+#include <stdarg.h>\r
+#include <time.h>\r
+#include <string.h>\r
+#include <signal.h>\r
+#include <getopt.h>\r
+#endif\r
+\r
+#include <infiniband/umad.h>\r
+#include <infiniband/mad.h>\r
+\r
+#include "ibdiag_common.h"\r
+\r
+#undef DEBUG\r
+#define        DEBUG   if (verbose) IBWARN\r
+\r
+static int dest_type = IB_DEST_LID;\r
+static int verbose;\r
+static char host_and_domain[IB_VENDOR_RANGE2_DATA_SIZE];\r
+static char last_host[IB_VENDOR_RANGE2_DATA_SIZE];\r
+\r
+char *argv0 = "ibping";\r
+\r
+static void\r
+get_host_and_domain(char *data, int sz)\r
+{\r
+       char *s = data;\r
+       int n;\r
+\r
+       if (gethostname(s, sz) < 0)\r
+               snprintf(s, sz, "?hostname?");\r
+\r
+       s[sz-1] = 0;\r
+       if ((n = strlen(s)) >= sz)\r
+               return;\r
+       s[n] = '.';\r
+       s += n + 1;\r
+       sz -= n + 1;\r
+\r
+       if (getdomainname(s, sz) < 0)\r
+               snprintf(s, sz, "?domainname?");\r
+       if (strlen(s) == 0)\r
+               s[-1] = 0;      /* no domain */\r
+}\r
+\r
+static char *\r
+ibping_serv(void)\r
+{\r
+       void *umad;\r
+       void *mad;\r
+       char *data;\r
+\r
+       DEBUG("starting to serve...");\r
+\r
+       while ((umad = mad_receive(0, -1))) {\r
+\r
+               mad = umad_get_mad(umad);\r
+               data = (char *)mad + IB_VENDOR_RANGE2_DATA_OFFS;\r
+\r
+               memcpy(data, host_and_domain, IB_VENDOR_RANGE2_DATA_SIZE);\r
+\r
+               DEBUG("Pong: %s", data);\r
+\r
+               if (mad_respond(umad, 0, 0) < 0)\r
+                       DEBUG("respond failed");\r
+\r
+               mad_free(umad);\r
+       }\r
+\r
+       DEBUG("server out");\r
+       return 0;\r
+}\r
+\r
+static uint64_t\r
+ibping(ib_portid_t *portid, int quiet)\r
+{\r
+       char data[IB_VENDOR_RANGE2_DATA_SIZE] = {0};\r
+       ib_vendor_call_t call;\r
+       uint64_t start, rtt;\r
+\r
+       DEBUG("Ping..");\r
+\r
+       start = getcurrenttime();\r
+\r
+       call.method = IB_MAD_METHOD_GET;\r
+       call.mgmt_class = IB_VENDOR_OPENIB_PING_CLASS;\r
+       call.attrid = 0;\r
+       call.mod = 0;\r
+       call.oui = IB_OPENIB_OUI;\r
+       call.timeout = 0;\r
+       memset(&call.rmpp, 0, sizeof call.rmpp);\r
+\r
+       if (!ib_vendor_call(data, portid, &call))\r
+               return ~0llu;\r
+\r
+       rtt = getcurrenttime() - start;\r
+\r
+       if (!last_host[0])\r
+               memcpy(last_host, data, sizeof last_host);\r
+\r
+       if (!quiet)\r
+               printf("Pong from %s (%s): time %" PRIu64 ".%03" PRIu64 " ms\n",\r
+                       data, portid2str(portid), rtt/1000, rtt%1000);\r
+\r
+       return rtt;\r
+}\r
+\r
+static void\r
+usage(void)\r
+{\r
+       char *basename;\r
+\r
+       if (!(basename = strrchr(argv0, '/')))\r
+               basename = argv0;\r
+       else\r
+               basename++;\r
+\r
+       fprintf(stderr, "Usage: %s [-d(ebug) -e(rr_show) -v(erbose) -G(uid) -s smlid -V(ersion) -C ca_name -P ca_port "\r
+                       "-t(imeout) timeout_ms -c ping_count -f(lood) -o oui -S(erver)] <dest lid|guid>\n",\r
+                       basename);\r
+       exit(-1);\r
+}\r
+\r
+static uint64_t minrtt = ~0ull, maxrtt, total_rtt;\r
+static uint64_t start, total_time, replied, lost, ntrans;\r
+static ib_portid_t portid = {0};\r
+\r
+void\r
+report(int sig)\r
+{\r
+       total_time = getcurrenttime() - start;\r
+\r
+       DEBUG("out due signal %d", sig);\r
+\r
+       printf("\n--- %s (%s) ibping statistics ---\n", last_host, portid2str(&portid));\r
+       printf("%" PRIu64 " packets transmitted, %" PRIu64 " received, %" PRIu64 "%% packet loss, time %" PRIu64 " ms\n",\r
+               ntrans, replied,\r
+               (lost != 0) ?  lost * 100 / ntrans : 0, total_time / 1000);\r
+       printf("rtt min/avg/max = %" PRIu64 ".%03" PRIu64 "/%" PRIu64 ".%03" PRIu64 "/%" PRIu64 ".%03" PRIu64 " ms\n",\r
+               minrtt == ~0ull ? 0 : minrtt/1000,\r
+               minrtt == ~0ull ? 0 : minrtt%1000,\r
+               replied ? total_rtt/replied/1000 : 0,\r
+               replied ? (total_rtt/replied)%1000 : 0,\r
+               maxrtt/1000, maxrtt%1000);\r
+\r
+       exit(0);\r
+}\r
+\r
+int\r
+main(int argc, char **argv)\r
+{\r
+       int mgmt_classes[3] = {IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS};\r
+       int ping_class = IB_VENDOR_OPENIB_PING_CLASS;\r
+       ib_portid_t *sm_id = 0, sm_portid = {0};\r
+       int timeout = 0, udebug = 0, server = 0, flood = 0;\r
+       int oui = IB_OPENIB_OUI;\r
+       uint64_t rtt;\r
+       uint count = ~0;\r
+       extern int ibdebug;\r
+       char *err;\r
+       char *ca = 0;\r
+       int ca_port = 0;\r
+\r
+       static char str_opts[] = "C:P:t:s:c:o:devGfSVhu";\r
+       static struct option long_opts[] = {\r
+               { "C", 1, 0, 'C'},\r
+               { "P", 1, 0, 'P'},\r
+               { "debug", 0, 0, 'd'},\r
+               { "err_show", 0, 0, 'e'},\r
+               { "verbose", 0, 0, 'v'},\r
+               { "Guid", 0, 0, 'G'},\r
+               { "s", 1, 0, 's'},\r
+               { "timeout", 1, 0, 't'},\r
+               { "c", 1, 0, 'c'},\r
+               { "flood", 0, 0, 'f'},\r
+               { "o", 1, 0, 'o'},\r
+               { "Server", 0, 0, 'S'},\r
+               { "Version", 0, 0, 'V'},\r
+               { "help", 0, 0, 'h'},\r
+               { "usage", 0, 0, 'u'},\r
+               { 0 }\r
+       };\r
+\r
+       argv0 = argv[0];\r
+\r
+       while (1) {\r
+               int ch = getopt_long(argc, argv, str_opts, long_opts, NULL);\r
+               if ( ch == -1 )\r
+                       break;\r
+               switch(ch) {\r
+               case 'C':\r
+                       ca = optarg;\r
+                       break;\r
+               case 'P':\r
+                       ca_port = strtoul(optarg, 0, 0);\r
+                       break;\r
+               case 'c':\r
+                       count = strtoul(optarg, 0, 0);\r
+                       break;\r
+               case 'd':\r
+                       ibdebug++;\r
+                       madrpc_show_errors(1);\r
+                       umad_debug(udebug);\r
+                       udebug++;\r
+                       break;\r
+               case 'e':\r
+                       madrpc_show_errors(1);\r
+                       break;\r
+               case 'f':\r
+                       flood++;\r
+                       break;\r
+               case 'G':\r
+                       dest_type = IB_DEST_GUID;\r
+                       break;\r
+               case 'o':\r
+                       oui = strtoul(optarg, 0, 0);\r
+                       break;\r
+               case 's':\r
+                       if (ib_resolve_portid_str(&sm_portid, optarg, IB_DEST_LID, 0) < 0)\r
+                               IBERROR("can't resolve SM destination port %s", optarg);\r
+                       sm_id = &sm_portid;\r
+                       break;\r
+               case 'S':\r
+                       server++;\r
+                       break;\r
+               case 't':\r
+                       timeout = strtoul(optarg, 0, 0);\r
+                       madrpc_set_timeout(timeout);\r
+                       break;\r
+               case 'v':\r
+                       verbose++;\r
+                       break;\r
+               case 'V':\r
+                       fprintf(stderr, "%s %s\n", argv0, get_build_version() );\r
+                       exit(-1);\r
+               default:\r
+                       usage();\r
+                       break;\r
+               }\r
+       }\r
+       argc -= optind;\r
+       argv += optind;\r
+\r
+       if (!argc && !server)\r
+               usage();\r
+\r
+       madrpc_init(ca, ca_port, mgmt_classes, 3);\r
+\r
+       if (server) {\r
+               if (mad_register_server(ping_class, 0, 0, oui) < 0)\r
+                       IBERROR("can't serve class %d on this port", ping_class);\r
+\r
+               get_host_and_domain(host_and_domain, sizeof host_and_domain);\r
+\r
+               if ((err = ibping_serv()))\r
+                       IBERROR("ibping to %s: %s", portid2str(&portid), err);\r
+               exit(0);\r
+       }\r
+\r
+       if (mad_register_client(ping_class, 0) < 0)\r
+               IBERROR("can't register ping class %d on this port", ping_class);\r
+\r
+       if (ib_resolve_portid_str(&portid, argv[0], dest_type, sm_id) < 0)\r
+               IBERROR("can't resolve destination port %s", argv[0]);\r
+\r
+       signal(SIGINT, report);\r
+       signal(SIGTERM, report);\r
+\r
+       start = getcurrenttime();\r
+\r
+       while (count-- > 0) {\r
+               ntrans++;\r
+               if ((rtt = ibping(&portid, flood)) == ~0ull) {\r
+                       DEBUG("ibping to %s failed", portid2str(&portid));\r
+                       lost++;\r
+               } else {\r
+                       if (rtt < minrtt)\r
+                               minrtt = rtt;\r
+                       if (rtt > maxrtt)\r
+                               maxrtt = rtt;\r
+                       total_rtt += rtt;\r
+                       replied++;\r
+               }\r
+\r
+               if (!flood)\r
+                       sleep(1);\r
+       }\r
+\r
+       report(0);\r
+\r
+       exit(-1);\r
+}\r
diff --git a/branches/winverbs/tools/infiniband_diags/src/ibping/SOURCES b/branches/winverbs/tools/infiniband_diags/src/ibping/SOURCES
new file mode 100644 (file)
index 0000000..0d9d896
--- /dev/null
@@ -0,0 +1,30 @@
+TARGETNAME = ibping\r
+TARGETPATH = ..\..\..\..\bin\user\obj$(BUILD_ALT_DIR)\r
+TARGETTYPE = PROGRAM\r
+\r
+UMTYPE = console\r
+UMENTRY = main\r
+\r
+USE_MSVCRT = 1\r
+USE_STL = 1\r
+USE_NATIVE_EH = 1\r
+USE_IOSTREAM = 1\r
+\r
+SOURCES = ..\ibping.c ..\ibdiag_common.c\r
+       \r
+INCLUDES = ..;..\..\include;..\..\..\..\ulp\libibmad\include;..\..\..\..\ulp\libibumad\include;..\..\..\..\inc;..\..\..\..\inc\user;\r
+\r
+TARGETLIBS =   \\r
+       $(SDK_LIB_PATH)\kernel32.lib    \\r
+       $(SDK_LIB_PATH)\advapi32.lib    \\r
+       $(SDK_LIB_PATH)\user32.lib      \\r
+       $(SDK_LIB_PATH)\ole32.lib       \\r
+       $(SDK_LIB_PATH)\ws2_32.lib      \\r
+!if $(FREEBUILD)\r
+       $(TARGETPATH)\*\libibmad.lib    \\r
+       $(TARGETPATH)\*\libibumad.lib   \r
+!else\r
+       $(TARGETPATH)\*\libibmadd.lib   \\r
+       $(TARGETPATH)\*\libibumadd.lib  \r
+!endif\r
+\r
diff --git a/branches/winverbs/tools/infiniband_diags/src/ibportstate.c b/branches/winverbs/tools/infiniband_diags/src/ibportstate.c
new file mode 100644 (file)
index 0000000..07d7a01
--- /dev/null
@@ -0,0 +1,448 @@
+/*\r
+ * Copyright (c) 2004-2008 Voltaire 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
+#if HAVE_CONFIG_H\r
+#  include <config.h>\r
+#endif /* HAVE_CONFIG_H */\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <unistd.h>\r
+#include <stdarg.h>\r
+#include <time.h>\r
+#include <string.h>\r
+#include <getopt.h>\r
+\r
+#include <infiniband/common.h>\r
+#include <infiniband/umad.h>\r
+#include <infiniband/mad.h>\r
+\r
+#include "ibdiag_common.h"\r
+\r
+#undef DEBUG\r
+#define        DEBUG   if (verbose>1) IBWARN\r
+\r
+static int dest_type = IB_DEST_LID;\r
+static int verbose;\r
+\r
+char *argv0 = "ibportstate";\r
+\r
+/*******************************************/\r
+\r
+static int\r
+get_node_info(ib_portid_t *dest, uint8_t *data)\r
+{\r
+       int node_type;\r
+\r
+       if (!smp_query(data, dest, IB_ATTR_NODE_INFO, 0, 0))\r
+               return -1;\r
+\r
+       node_type = mad_get_field(data, 0, IB_NODE_TYPE_F);\r
+       if (node_type == IB_NODE_SWITCH)        /* Switch NodeType ? */\r
+               return 0;\r
+       else\r
+               return 1;\r
+}\r
+\r
+static int\r
+get_port_info(ib_portid_t *dest, uint8_t *data, int portnum, int port_op)\r
+{\r
+       char buf[2048];\r
+       char val[64];\r
+\r
+       if (!smp_query(data, dest, IB_ATTR_PORT_INFO, portnum, 0))\r
+               return -1;\r
+\r
+       if (port_op != 4) {\r
+               mad_dump_portstates(buf, sizeof buf, data, sizeof data);\r
+               mad_decode_field(data, IB_PORT_LINK_WIDTH_SUPPORTED_F, val);\r
+               mad_dump_field(IB_PORT_LINK_WIDTH_SUPPORTED_F, buf + strlen(buf), sizeof buf - strlen(buf), val);\r
+               sprintf(buf+strlen(buf), "%s", "\n");\r
+               mad_decode_field(data, IB_PORT_LINK_WIDTH_ENABLED_F, val);\r
+               mad_dump_field(IB_PORT_LINK_WIDTH_ENABLED_F, buf + strlen(buf), sizeof buf - strlen(buf), val);\r
+               sprintf(buf+strlen(buf), "%s", "\n");\r
+               mad_decode_field(data, IB_PORT_LINK_WIDTH_ACTIVE_F, val);\r
+               mad_dump_field(IB_PORT_LINK_WIDTH_ACTIVE_F, buf + strlen(buf), sizeof buf - strlen(buf), val);\r
+               sprintf(buf+strlen(buf), "%s", "\n");\r
+               mad_decode_field(data, IB_PORT_LINK_SPEED_SUPPORTED_F, val);\r
+               mad_dump_field(IB_PORT_LINK_SPEED_SUPPORTED_F, buf + strlen(buf), sizeof buf - strlen(buf), val);\r
+               sprintf(buf+strlen(buf), "%s", "\n");\r
+               mad_decode_field(data, IB_PORT_LINK_SPEED_ENABLED_F, val);\r
+               mad_dump_field(IB_PORT_LINK_SPEED_ENABLED_F, buf + strlen(buf), sizeof buf - strlen(buf), val);\r
+               sprintf(buf+strlen(buf), "%s", "\n");\r
+               mad_decode_field(data, IB_PORT_LINK_SPEED_ACTIVE_F, val);\r
+               mad_dump_field(IB_PORT_LINK_SPEED_ACTIVE_F, buf + strlen(buf), sizeof buf - strlen(buf), val);\r
+               sprintf(buf+strlen(buf), "%s", "\n");\r
+       } else {\r
+               mad_decode_field(data, IB_PORT_LINK_SPEED_ENABLED_F, val);\r
+               mad_dump_field(IB_PORT_LINK_SPEED_ENABLED_F, buf, sizeof buf, val);\r
+               sprintf(buf+strlen(buf), "%s", "\n");\r
+       }\r
+\r
+       printf("# Port info: %s port %d\n%s", portid2str(dest), portnum, buf);\r
+       return 0;\r
+}\r
+\r
+static int\r
+set_port_info(ib_portid_t *dest, uint8_t *data, int portnum, int port_op)\r
+{\r
+       char buf[2048];\r
+       char val[64];\r
+\r
+       if (!smp_set(data, dest, IB_ATTR_PORT_INFO, portnum, 0))\r
+               return -1;\r
+\r
+       if (port_op != 4)\r
+               mad_dump_portstates(buf, sizeof buf, data, sizeof data);\r
+       else {\r
+               mad_decode_field(data, IB_PORT_LINK_SPEED_ENABLED_F, val);\r
+               mad_dump_field(IB_PORT_LINK_SPEED_ENABLED_F, buf, sizeof buf, val);\r
+               sprintf(buf+strlen(buf), "%s", "\n");\r
+       }\r
+\r
+       printf("\nAfter PortInfo set:\n");\r
+       printf("# Port info: %s port %d\n%s", portid2str(dest), portnum, buf);\r
+       return 0;\r
+}\r
+\r
+static int\r
+get_link_width(int lwe, int lws)\r
+{\r
+       if (lwe == 255)\r
+               return lws;\r
+       else\r
+               return lwe;\r
+}\r
+\r
+static int\r
+get_link_speed(int lse, int lss)\r
+{\r
+       if (lse == 15)\r
+               return lss;\r
+       else\r
+               return lse;\r
+}\r
+\r
+static void\r
+validate_width(int width, int peerwidth, int lwa)\r
+{\r
+       if ((width & 0x8) && (peerwidth & 0x8)) {\r
+               if (lwa != 8)\r
+                       IBWARN("Peer ports operating at active width %d rather than 8 (12x)", lwa);\r
+       } else {\r
+               if ((width & 0x4) && (peerwidth & 0x4)) {\r
+                       if (lwa != 4)\r
+                               IBWARN("Peer ports operating at active width %d rather than 4 (8x)", lwa);\r
+               } else {\r
+                       if ((width & 0x2) && (peerwidth & 0x2)) {\r
+                               if (lwa != 2)\r
+                                       IBWARN("Peer ports operating at active width %d rather than 2 (4x)", lwa);\r
+                       } else {\r
+                               if ((width & 0x1) && (peerwidth & 0x1)) {\r
+                                       if (lwa != 1)\r
+                                               IBWARN("Peer ports operating at active width %d rather than 1 (1x)", lwa);\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+}\r
+\r
+static void\r
+validate_speed(int speed, int peerspeed, int lsa)\r
+{\r
+       if ((speed & 0x4) && (peerspeed & 0x4)) {\r
+               if (lsa != 4)\r
+                       IBWARN("Peer ports operating at active speed %d rather than  4 (10.0 Gbps)", lsa);\r
+       } else {\r
+               if ((speed & 0x2) && (peerspeed & 0x2)) {\r
+                       if (lsa != 2)\r
+                               IBWARN("Peer ports operating at active speed %d rather than 2 (5.0 Gbps)", lsa);\r
+               } else {\r
+                       if ((speed & 0x1) && (peerspeed & 0x1)) {\r
+                               if (lsa != 1)\r
+                                       IBWARN("Peer ports operating at active speed %d rather than 1 (2.5 Gbps)", lsa);\r
+                       }\r
+               }\r
+       }\r
+}\r
+\r
+void\r
+usage(void)\r
+{\r
+       char *basename;\r
+\r
+       if (!(basename = strrchr(argv0, '/')))\r
+               basename = argv0;\r
+       else\r
+               basename++;\r
+\r
+       fprintf(stderr, "Usage: %s [-d(ebug) -e(rr_show) -v(erbose) -D(irect) -G(uid) -s smlid -V(ersion) -C ca_name -P ca_port "\r
+                       "-t(imeout) timeout_ms] <dest dr_path|lid|guid> <portnum> [<op>]\n",\r
+                       basename);\r
+       fprintf(stderr, "\tsupported ops: enable, disable, reset, speed, query\n");\r
+       fprintf(stderr, "\n\texamples:\n");\r
+       fprintf(stderr, "\t\t%s 3 1 disable\t\t\t# by lid\n", basename);\r
+       fprintf(stderr, "\t\t%s -G 0x2C9000100D051 1 enable\t# by guid\n", basename);\r
+       fprintf(stderr, "\t\t%s -D 0 1\t\t\t# (query) by direct route\n", basename);\r
+       fprintf(stderr, "\t\t%s 3 1 reset\t\t\t# by lid\n", basename);\r
+       fprintf(stderr, "\t\t%s 3 1 speed 1\t\t\t# by lid\n", basename);\r
+       exit(-1);\r
+}\r
+\r
+int\r
+main(int argc, char **argv)\r
+{\r
+       int mgmt_classes[3] = {IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS};\r
+       ib_portid_t portid = {0};\r
+       ib_portid_t *sm_id = 0, sm_portid = {0};\r
+       extern int ibdebug;\r
+       int err;\r
+       int timeout = 0, udebug = 0;\r
+       char *ca = 0;\r
+       int ca_port = 0;\r
+       int port_op = 0;        /* default to query */\r
+       int speed = 15;\r
+       int is_switch = 1;\r
+       int state, physstate, lwe, lws, lwa, lse, lss, lsa;\r
+       int peerlocalportnum, peerlwe, peerlws, peerlwa, peerlse, peerlss, peerlsa;\r
+       int width, peerwidth, peerspeed;\r
+       uint8_t data[IB_SMP_DATA_SIZE];\r
+       ib_portid_t peerportid = {0};\r
+       int portnum = 0;\r
+       ib_portid_t selfportid = {0};\r
+       int selfport = 0;\r
+\r
+       static char const str_opts[] = "C:P:t:s:devDGVhu";\r
+       static const struct option long_opts[] = {\r
+               { "C", 1, 0, 'C'},\r
+               { "P", 1, 0, 'P'},\r
+               { "debug", 0, 0, 'd'},\r
+               { "err_show", 0, 0, 'e'},\r
+               { "verbose", 0, 0, 'v'},\r
+               { "Direct", 0, 0, 'D'},\r
+               { "Guid", 0, 0, 'G'},\r
+               { "timeout", 1, 0, 't'},\r
+               { "s", 1, 0, 's'},\r
+               { "Version", 0, 0, 'V'},\r
+               { "help", 0, 0, 'h'},\r
+               { "usage", 0, 0, 'u'},\r
+               { }\r
+       };\r
+\r
+       argv0 = argv[0];\r
+\r
+       while (1) {\r
+               int ch = getopt_long(argc, argv, str_opts, long_opts, NULL);\r
+               if ( ch == -1 )\r
+                       break;\r
+               switch(ch) {\r
+               case 'd':\r
+                       ibdebug++;\r
+                       madrpc_show_errors(1);\r
+                       umad_debug(udebug);\r
+                       udebug++;\r
+                       break;\r
+               case 'e':\r
+                       madrpc_show_errors(1);\r
+                       break;\r
+               case 'D':\r
+                       dest_type = IB_DEST_DRPATH;\r
+                       break;\r
+               case 'G':\r
+                       dest_type = IB_DEST_GUID;\r
+                       break;\r
+               case 'C':\r
+                       ca = optarg;\r
+                       break;\r
+               case 'P':\r
+                       ca_port = strtoul(optarg, 0, 0);\r
+                       break;\r
+               case 's':\r
+                       if (ib_resolve_portid_str(&sm_portid, optarg, IB_DEST_LID, 0) < 0)\r
+                               IBERROR("can't resolve SM destination port %s", optarg);\r
+                       sm_id = &sm_portid;\r
+                       break;\r
+               case 't':\r
+                       timeout = strtoul(optarg, 0, 0);\r
+                       madrpc_set_timeout(timeout);\r
+                       break;\r
+               case 'v':\r
+                       verbose++;\r
+                       break;\r
+               case 'V':\r
+                       fprintf(stderr, "%s %s\n", argv0, get_build_version() );\r
+                       exit(-1);\r
+               default:\r
+                       usage();\r
+                       break;\r
+               }\r
+       }\r
+       argc -= optind;\r
+       argv += optind;\r
+\r
+       if (argc < 2)\r
+               usage();\r
+\r
+       madrpc_init(ca, ca_port, mgmt_classes, 3);\r
+\r
+       if (ib_resolve_portid_str(&portid, argv[0], dest_type, sm_id) < 0)\r
+               IBERROR("can't resolve destination port %s", argv[0]);\r
+\r
+       /* First, make sure it is a switch port if it is a "set" */\r
+       if (argc >= 3) {\r
+               if (!strcmp(argv[2], "enable"))\r
+                       port_op = 1;\r
+               else if (!strcmp(argv[2], "disable"))\r
+                       port_op = 2;\r
+               else if (!strcmp(argv[2], "reset"))\r
+                       port_op = 3;\r
+               else if (!strcmp(argv[2], "speed")) {\r
+                       if (argc < 4)\r
+                               IBERROR("speed requires an additional parameter");\r
+                       port_op = 4;\r
+                       /* Parse speed value */\r
+                       speed = strtoul(argv[3], 0, 0);\r
+                       if (speed > 15)\r
+                               IBERROR("invalid speed value %d", speed);\r
+               }\r
+       }\r
+\r
+       err = get_node_info(&portid, data);\r
+       if (err < 0)\r
+               IBERROR("smp query nodeinfo failed");\r
+       if (err) {              /* not switch */\r
+               if (port_op == 0)       /* query op */\r
+                       is_switch = 0;\r
+               else if (port_op != 4)  /* other than speed op */\r
+                       IBERROR("smp query nodeinfo: Node type not switch");\r
+       }\r
+\r
+       if (argc-1 > 0)\r
+               portnum = strtol(argv[1], 0, 0);\r
+\r
+       if (port_op)\r
+               printf("Initial PortInfo:\n");\r
+       else\r
+               printf("PortInfo:\n");\r
+       err = get_port_info(&portid, data, portnum, port_op);\r
+       if (err < 0)\r
+               IBERROR("smp query portinfo failed");\r
+\r
+       /* Only if one of the "set" options is chosen */\r
+       if (port_op) {\r
+               if (port_op == 1)               /* Enable port */\r
+                       mad_set_field(data, 0, IB_PORT_PHYS_STATE_F, 2);        /* Polling */\r
+               else if ((port_op == 2) || (port_op == 3)) { /* Disable port */\r
+                       mad_set_field(data, 0, IB_PORT_STATE_F, 1);             /* Down */\r
+                       mad_set_field(data, 0, IB_PORT_PHYS_STATE_F, 3);        /* Disabled */\r
+               } else if (port_op == 4) {      /* Set speed */\r
+                       mad_set_field(data, 0, IB_PORT_LINK_SPEED_ENABLED_F, speed);\r
+                       mad_set_field(data, 0, IB_PORT_STATE_F, 0);\r
+                       mad_set_field(data, 0, IB_PORT_PHYS_STATE_F, 0);\r
+               }\r
+\r
+               err = set_port_info(&portid, data, portnum, port_op);\r
+               if (err < 0)\r
+                       IBERROR("smp set portinfo failed");\r
+\r
+               if (port_op == 3) {     /* Reset port - so also enable */\r
+                       mad_set_field(data, 0, IB_PORT_PHYS_STATE_F, 2);        /* Polling */\r
+                       err = set_port_info(&portid, data, portnum, port_op);\r
+                       if (err < 0)\r
+                               IBERROR("smp set portinfo failed");\r
+               }\r
+       } else {        /* query op */\r
+               /* only compare peer port if switch port */\r
+               if (is_switch) {\r
+                       /* First, exclude SP0 */\r
+                       if (portnum) {\r
+                               /* Now, make sure PortState is Active */\r
+                               /* Or is PortPhysicalState LinkUp sufficient ? */\r
+                               mad_decode_field(data, IB_PORT_STATE_F, &state);\r
+                               mad_decode_field(data, IB_PORT_PHYS_STATE_F, &physstate);\r
+                               if (state == 4) {       /* Active */\r
+                                       mad_decode_field(data, IB_PORT_LINK_WIDTH_ENABLED_F, &lwe );\r
+                                       mad_decode_field(data, IB_PORT_LINK_WIDTH_SUPPORTED_F, &lws);\r
+                                       mad_decode_field(data, IB_PORT_LINK_WIDTH_ACTIVE_F, &lwa);\r
+                                       mad_decode_field(data, IB_PORT_LINK_SPEED_SUPPORTED_F, &lss);\r
+                                       mad_decode_field(data, IB_PORT_LINK_SPEED_ACTIVE_F, &lsa);\r
+                                       mad_decode_field(data, IB_PORT_LINK_SPEED_ENABLED_F, &lse);\r
+\r
+                                       /* Setup portid for peer port */\r
+                                       memcpy(&peerportid, &portid, sizeof(peerportid));\r
+                                       peerportid.drpath.cnt = 1;\r
+                                       peerportid.drpath.p[1] = portnum;\r
+\r
+                                       /* Set DrSLID to local lid */\r
+                                       if (ib_resolve_self(&selfportid, &selfport, 0) < 0)\r
+                                               IBERROR("could not resolve self");\r
+                                       peerportid.drpath.drslid = selfportid.lid;\r
+                                       peerportid.drpath.drdlid = 0xffff;\r
+\r
+                                       /* Get peer port NodeInfo to obtain peer port number */\r
+                                       err = get_node_info(&peerportid, data);\r
+                                       if (err < 0)\r
+                                               IBERROR("smp query nodeinfo failed");\r
+\r
+                                       mad_decode_field(data, IB_NODE_LOCAL_PORT_F, &peerlocalportnum);\r
+\r
+                                       printf("Peer PortInfo:\n");\r
+                                       /* Get peer port characteristics */\r
+                                       err = get_port_info(&peerportid, data, peerlocalportnum, port_op);\r
+                                       if (err < 0)\r
+                                               IBERROR("smp query peer portinfofailed");\r
+\r
+                                       mad_decode_field(data, IB_PORT_LINK_WIDTH_ENABLED_F, &peerlwe );\r
+                                       mad_decode_field(data, IB_PORT_LINK_WIDTH_SUPPORTED_F, &peerlws);\r
+                                       mad_decode_field(data, IB_PORT_LINK_WIDTH_ACTIVE_F, &peerlwa);\r
+                                       mad_decode_field(data, IB_PORT_LINK_SPEED_SUPPORTED_F, &peerlss);\r
+                                       mad_decode_field(data, IB_PORT_LINK_SPEED_ACTIVE_F, &peerlsa);\r
+                                       mad_decode_field(data, IB_PORT_LINK_SPEED_ENABLED_F, &peerlse);\r
+\r
+                                       /* Now validate peer port characteristics */\r
+                                       /* Examine Link Width */\r
+                                       width = get_link_width(lwe, lws);\r
+                                       peerwidth = get_link_width(peerlwe, peerlws);\r
+                                       validate_width(width, peerwidth, lwa);\r
+\r
+                                       /* Examine Link Speed */\r
+                                       speed = get_link_speed(lse, lss);\r
+                                       peerspeed = get_link_speed(peerlse, peerlss);\r
+                                       validate_speed(speed, peerspeed, lsa);\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+\r
+       exit(0);\r
+}\r
diff --git a/branches/winverbs/tools/infiniband_diags/src/ibroute.c b/branches/winverbs/tools/infiniband_diags/src/ibroute.c
new file mode 100644 (file)
index 0000000..83e2142
--- /dev/null
@@ -0,0 +1,495 @@
+/*\r
+ * Copyright (c) 2004-2008 Voltaire 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
+#if HAVE_CONFIG_H\r
+#  include <config.h>\r
+#endif /* HAVE_CONFIG_H */\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <unistd.h>\r
+#include <stdarg.h>\r
+#include <time.h>\r
+#include <string.h>\r
+#include <inttypes.h>\r
+#include <getopt.h>\r
+#include <netinet/in.h>\r
+#include <ctype.h>\r
+\r
+#include <infiniband/common.h>\r
+#include <infiniband/umad.h>\r
+#include <infiniband/mad.h>\r
+#include <infiniband/complib/cl_nodenamemap.h>\r
+\r
+#include "ibdiag_common.h"\r
+\r
+static int dest_type = IB_DEST_LID;\r
+static int brief;\r
+static int verbose;\r
+static int dump_all;\r
+\r
+char *argv0 = "ibroute";\r
+\r
+/*******************************************/\r
+\r
+char *\r
+check_switch(ib_portid_t *portid, int *nports, uint64_t *guid,\r
+            uint8_t *sw, char *nd)\r
+{\r
+       uint8_t ni[IB_SMP_DATA_SIZE] = {0};\r
+       int type;\r
+\r
+       DEBUG("checking node type");\r
+       if (!smp_query(ni, portid, IB_ATTR_NODE_INFO, 0, 0)) {\r
+               xdump(stderr, "nodeinfo\n", ni, sizeof ni);\r
+               return "node info failed: valid addr?";\r
+       }\r
+\r
+       if (!smp_query(nd, portid, IB_ATTR_NODE_DESC, 0, 0))\r
+               return "node desc failed";\r
+\r
+       mad_decode_field(ni, IB_NODE_TYPE_F, &type);\r
+       if (type != IB_NODE_SWITCH)\r
+               return "not a switch";\r
+\r
+       DEBUG("Gathering information about switch");\r
+       mad_decode_field(ni, IB_NODE_NPORTS_F, nports);\r
+       mad_decode_field(ni, IB_NODE_GUID_F, guid);\r
+\r
+       if (!smp_query(sw, portid, IB_ATTR_SWITCH_INFO, 0, 0))\r
+               return "switch info failed: is a switch node?";\r
+\r
+       return 0;\r
+}\r
+\r
+#define IB_MLIDS_IN_BLOCK      (IB_SMP_DATA_SIZE/2)\r
+\r
+int\r
+dump_mlid(char *str, int strlen, int mlid, int nports,\r
+         uint16_t mft[16][IB_MLIDS_IN_BLOCK])\r
+{\r
+       uint16_t mask;\r
+       int i, chunk, bit;\r
+       int nonzero = 0;\r
+\r
+       if (brief) {\r
+               int n = 0, chunks = ALIGN(nports + 1, 16) / 16;\r
+               for (i = 0; i < chunks; i++) {\r
+                       mask = ntohs(mft[i][mlid%IB_MLIDS_IN_BLOCK]);\r
+                       if (mask)\r
+                               nonzero++;\r
+                       n += snprintf(str + n, strlen - n, "%04hx", mask);\r
+                       if (n >= strlen) {\r
+                               n = strlen;\r
+                               break;\r
+                       }\r
+               }\r
+               if (!nonzero && !dump_all) {\r
+                       str[0] = 0;\r
+                       return 0;\r
+               }\r
+               return n;\r
+       }\r
+       for (i = 0; i <= nports; i++) {\r
+               chunk = i / 16;\r
+               bit = i % 16;\r
+\r
+               mask = ntohs(mft[chunk][mlid%IB_MLIDS_IN_BLOCK]);\r
+               if (mask)\r
+                       nonzero++;\r
+               str[i*2] = (mask & (1 << bit)) ? 'x' : ' ';\r
+               str[i*2+1] = ' ';\r
+       }\r
+       if (!nonzero && !dump_all) {\r
+               str[0] = 0;\r
+               return 0;\r
+       }\r
+       str[i*2] = 0;\r
+       return i * 2;\r
+}\r
+\r
+uint16_t mft[16][IB_MLIDS_IN_BLOCK];\r
+\r
+char *\r
+dump_multicast_tables(ib_portid_t *portid, int startlid, int endlid)\r
+{\r
+       char nd[IB_SMP_DATA_SIZE] = {0};\r
+       uint8_t sw[IB_SMP_DATA_SIZE] = {0};\r
+       char str[512];\r
+       char *s;\r
+       uint64_t nodeguid;\r
+       uint32_t mod;\r
+       int block, i, j, e, nports, cap, chunks;\r
+       int n = 0, startblock, lastblock;\r
+\r
+       if ((s = check_switch(portid, &nports, &nodeguid, sw, nd)))\r
+               return s;\r
+\r
+       mad_decode_field(sw, IB_SW_MCAST_FDB_CAP_F, &cap);\r
+\r
+       if (!endlid || endlid > IB_MIN_MCAST_LID + cap - 1)\r
+               endlid = IB_MIN_MCAST_LID + cap - 1;\r
+\r
+       if (!startlid)\r
+               startlid = IB_MIN_MCAST_LID;\r
+\r
+       if (startlid < IB_MIN_MCAST_LID) {\r
+               IBWARN("illegal start mlid %x, set to %x", startlid, IB_MIN_MCAST_LID);\r
+               startlid = IB_MIN_MCAST_LID;\r
+       }\r
+\r
+       if (endlid > IB_MAX_MCAST_LID) {\r
+               IBWARN("illegal end mlid %x, truncate to %x", endlid, IB_MAX_MCAST_LID);\r
+               endlid = IB_MAX_MCAST_LID;\r
+       }\r
+\r
+       printf("Multicast mlids [0x%x-0x%x] of switch %s guid 0x%016" PRIx64 " (%s):\n",\r
+               startlid, endlid, portid2str(portid), nodeguid, clean_nodedesc(nd));\r
+\r
+       if (brief)\r
+               printf(" MLid       Port Mask\n");\r
+       else {\r
+               if (nports > 9) {\r
+                       for (i = 0, s = str; i <= nports; i++) {\r
+                               *s++ = (i%10) ? ' ' : '0' + i/10;\r
+                               *s++ = ' ';\r
+                       }\r
+                       *s = 0;\r
+                       printf("            %s\n", str);\r
+               }\r
+               for (i = 0, s = str; i <= nports; i++)\r
+                       s += sprintf(s, "%d ", i%10);\r
+               printf("     Ports: %s\n", str);\r
+               printf(" MLid\n");\r
+       }\r
+       if (verbose)\r
+               printf("Switch muticast mlids capability is 0x%d\n", cap);\r
+\r
+       chunks = ALIGN(nports + 1, 16) / 16;\r
+\r
+       startblock = startlid / IB_MLIDS_IN_BLOCK;\r
+       lastblock = endlid / IB_MLIDS_IN_BLOCK;\r
+       for (block = startblock; block <= lastblock; block++) {\r
+               for (j = 0; j < chunks; j++) {\r
+                       mod = (block - IB_MIN_MCAST_LID/IB_MLIDS_IN_BLOCK) | (j << 28);\r
+\r
+                       DEBUG("reading block %x chunk %d mod %x", block, j, mod);\r
+                       if (!smp_query(mft + j, portid, IB_ATTR_MULTICASTFORWTBL, mod, 0))\r
+                               return "multicast forwarding table get failed";\r
+               }\r
+\r
+               i = block * IB_MLIDS_IN_BLOCK;\r
+               e = i + IB_MLIDS_IN_BLOCK;\r
+               if (i < startlid)\r
+                       i = startlid;\r
+               if (e > endlid + 1)\r
+                       e = endlid + 1;\r
+\r
+               for (; i < e; i++) {\r
+                       if (dump_mlid(str, sizeof str, i, nports, mft) == 0)\r
+                               continue;\r
+                       printf("0x%04x      %s\n", i, str);\r
+                       n++;\r
+               }\r
+       }\r
+\r
+       printf("%d %smlids dumped \n", n, dump_all ? "" : "valid ");\r
+       return 0;\r
+}\r
+\r
+int\r
+dump_lid(char *str, int strlen, int lid, int valid)\r
+{\r
+       char nd[IB_SMP_DATA_SIZE] = {0};\r
+       uint8_t ni[IB_SMP_DATA_SIZE] = {0};\r
+       uint8_t pi[IB_SMP_DATA_SIZE] = {0};\r
+       ib_portid_t lidport = {0};\r
+       static int last_port_lid, base_port_lid;\r
+       char ntype[50], sguid[30], desc[64];\r
+       static uint64_t portguid;\r
+       int baselid, lmc, type;\r
+\r
+       if (brief) {\r
+               str[0] = 0;\r
+               return 0;\r
+       }\r
+\r
+       if (lid <= last_port_lid) {\r
+               if (!valid)\r
+                       return snprintf(str, strlen, ": (path #%d - illegal port)",\r
+                                       lid - base_port_lid);\r
+               else if (!portguid)\r
+                       return snprintf(str, strlen,\r
+                                       ": (path #%d out of %d)",\r
+                                       lid - base_port_lid + 1,\r
+                                       last_port_lid - base_port_lid + 1);\r
+               else {\r
+                       return snprintf(str, strlen,\r
+                                       ": (path #%d out of %d: portguid %s)",\r
+                                       lid - base_port_lid + 1,\r
+                                       last_port_lid - base_port_lid + 1,\r
+                                       mad_dump_val(IB_NODE_PORT_GUID_F, sguid, sizeof sguid, &portguid));\r
+               }\r
+       }\r
+\r
+       if (!valid)\r
+               return snprintf(str, strlen, ": (illegal port)");\r
+\r
+       portguid = 0;\r
+       lidport.lid = lid;\r
+\r
+       if (!smp_query(nd, &lidport, IB_ATTR_NODE_DESC, 0, 100) ||\r
+           !smp_query(pi, &lidport, IB_ATTR_PORT_INFO, 0, 100) ||\r
+           !smp_query(ni, &lidport, IB_ATTR_NODE_INFO, 0, 100))\r
+               return snprintf(str, strlen, ": (unknown node and type)");\r
+\r
+       mad_decode_field(ni, IB_NODE_PORT_GUID_F, &portguid);\r
+       mad_decode_field(ni, IB_NODE_TYPE_F, &type);\r
+\r
+       mad_decode_field(pi, IB_PORT_LID_F, &baselid);\r
+       mad_decode_field(pi, IB_PORT_LMC_F, &lmc);\r
+\r
+       if (lmc > 0) {\r
+               base_port_lid = baselid;\r
+               last_port_lid = baselid + (1 << lmc) - 1;\r
+       }\r
+\r
+       return snprintf(str, strlen, ": (%s portguid %s: %s)",\r
+               mad_dump_val(IB_NODE_TYPE_F, ntype, sizeof ntype, &type),\r
+               mad_dump_val(IB_NODE_PORT_GUID_F, sguid, sizeof sguid, &portguid),\r
+               mad_dump_val(IB_NODE_DESC_F, desc, sizeof desc, clean_nodedesc(nd)));\r
+}\r
+\r
+char *\r
+dump_unicast_tables(ib_portid_t *portid, int startlid, int endlid)\r
+{\r
+       char lft[IB_SMP_DATA_SIZE];\r
+       char nd[IB_SMP_DATA_SIZE];\r
+       uint8_t sw[IB_SMP_DATA_SIZE];\r
+       char str[200], *s;\r
+       uint64_t nodeguid;\r
+       int block, i, e, nports, top;\r
+       int n = 0, startblock, endblock;\r
+\r
+       if ((s = check_switch(portid, &nports, &nodeguid, sw, nd)))\r
+               return s;\r
+\r
+       mad_decode_field(sw, IB_SW_LINEAR_FDB_TOP_F, &top);\r
+\r
+       if (!endlid || endlid > top)\r
+               endlid = top;\r
+\r
+       if (endlid > IB_MAX_UCAST_LID) {\r
+               IBWARN("ilegal lft top %d, truncate to %d", endlid, IB_MAX_UCAST_LID);\r
+               endlid = IB_MAX_UCAST_LID;\r
+       }\r
+\r
+       printf("Unicast lids [0x%x-0x%x] of switch %s guid 0x%016" PRIx64 " (%s):\n",\r
+               startlid, endlid, portid2str(portid), nodeguid, clean_nodedesc(nd));\r
+\r
+       DEBUG("Switch top is 0x%x\n", top);\r
+\r
+       printf("  Lid  Out   Destination\n");\r
+       printf("       Port     Info \n");\r
+       startblock = startlid / IB_SMP_DATA_SIZE;\r
+       endblock = ALIGN(endlid, IB_SMP_DATA_SIZE) / IB_SMP_DATA_SIZE;\r
+       for (block = startblock; block <= endblock; block++) {\r
+               DEBUG("reading block %d", block);\r
+               if (!smp_query(lft, portid, IB_ATTR_LINEARFORWTBL, block, 0))\r
+                       return "linear forwarding table get failed";\r
+               i = block * IB_SMP_DATA_SIZE;\r
+               e = i + IB_SMP_DATA_SIZE;\r
+               if (i < startlid)\r
+                       i = startlid;\r
+               if (e > endlid + 1)\r
+                       e = endlid + 1;\r
+\r
+               for (;i < e; i++) {\r
+                       unsigned outport = lft[i % IB_SMP_DATA_SIZE];\r
+                       unsigned valid = (outport <= nports);\r
+\r
+                       if (!valid && !dump_all)\r
+                               continue;\r
+                       dump_lid(str, sizeof str, i, valid);\r
+                       printf("0x%04x %03u %s\n", i, outport & 0xff, str);\r
+                       n++;\r
+               }\r
+       }\r
+\r
+       printf("%d %slids dumped \n", n, dump_all ? "" : "valid ");\r
+       return 0;\r
+}\r
+\r
+void\r
+usage(void)\r
+{\r
+       char *basename;\r
+\r
+       if (!(basename = strrchr(argv0, '/')))\r
+               basename = argv0;\r
+       else\r
+               basename++;\r
+\r
+       fprintf(stderr, "Usage: %s [-d(ebug)] -a(ll) -n(o_dests) -v(erbose) -D(irect) -G(uid) -M(ulticast) -s smlid -V(ersion) -C ca_name -P ca_port "\r
+                       "-t(imeout) timeout_ms] [<dest dr_path|lid|guid> [<startlid> [<endlid>]]]\n",\r
+                       basename);\r
+       fprintf(stderr, "\n\tUnicast examples:\n");\r
+       fprintf(stderr, "\t\t%s 4\t# dump all lids with valid out ports of switch with lid 4\n", basename);\r
+       fprintf(stderr, "\t\t%s -a 4\t# same, but dump all lids, even with invalid out ports\n", basename);\r
+       fprintf(stderr, "\t\t%s -n 4\t# simple dump format - no destination resolving\n", basename);\r
+       fprintf(stderr, "\t\t%s 4 10\t# dump lids starting from 10\n", basename);\r
+       fprintf(stderr, "\t\t%s 4 0x10 0x20\t# dump lid range\n", basename);\r
+       fprintf(stderr, "\t\t%s -G 0x08f1040023\t# resolve switch by GUID\n", basename);\r
+       fprintf(stderr, "\t\t%s -D 0,1\t# resolve switch by direct path\n", basename);\r
+\r
+       fprintf(stderr, "\n\tMulticast examples:\n");\r
+       fprintf(stderr, "\t\t%s -M 4\t# dump all non empty mlids of switch with lid 4\n", basename);\r
+       fprintf(stderr, "\t\t%s -M 4 0xc010 0xc020\t# same, but with range\n", basename);\r
+       fprintf(stderr, "\t\t%s -M -n 4\t# simple dump format\n", basename);\r
+       exit(-1);\r
+}\r
+\r
+int\r
+main(int argc, char **argv)\r
+{\r
+       int mgmt_classes[3] = {IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS};\r
+       ib_portid_t portid = {0};\r
+       ib_portid_t *sm_id = 0, sm_portid = {0};\r
+       int timeout;\r
+       int multicast = 0, startlid = 0, endlid = 0;\r
+       char *err;\r
+       char *ca = 0;\r
+       int ca_port = 0;\r
+\r
+       static char const str_opts[] = "C:P:t:s:danvDGMVhu";\r
+       static const struct option long_opts[] = {\r
+               { "C", 1, 0, 'C'},\r
+               { "P", 1, 0, 'P'},\r
+               { "debug", 0, 0, 'd'},\r
+               { "all", 0, 0, 'a'},\r
+               { "no_dests", 0, 0, 'n'},\r
+               { "verbose", 0, 0, 'v'},\r
+               { "Direct", 0, 0, 'D'},\r
+               { "Guid", 0, 0, 'G'},\r
+               { "Multicast", 0, 0, 'M'},\r
+               { "timeout", 1, 0, 't'},\r
+               { "s", 1, 0, 's'},\r
+               { "Version", 0, 0, 'V'},\r
+               { "help", 0, 0, 'h'},\r
+               { "usage", 0, 0, 'u'},\r
+               { }\r
+       };\r
+\r
+       argv0 = argv[0];\r
+\r
+       while (1) {\r
+               int ch = getopt_long(argc, argv, str_opts, long_opts, NULL);\r
+               if ( ch == -1 )\r
+                       break;\r
+               switch(ch) {\r
+               case 'C':\r
+                       ca = optarg;\r
+                       break;\r
+               case 'P':\r
+                       ca_port = strtoul(optarg, 0, 0);\r
+                       break;\r
+               case 'a':\r
+                       dump_all++;\r
+                       break;\r
+               case 'd':\r
+                       ibdebug++;\r
+                       break;\r
+               case 'D':\r
+                       dest_type = IB_DEST_DRPATH;\r
+                       break;\r
+               case 'G':\r
+                       dest_type = IB_DEST_GUID;\r
+                       break;\r
+               case 'M':\r
+                       multicast++;\r
+                       break;\r
+               case 'n':\r
+                       brief++;\r
+                       break;\r
+               case 's':\r
+                       if (ib_resolve_portid_str(&sm_portid, optarg, IB_DEST_LID, 0) < 0)\r
+                               IBERROR("can't resolve SM destination port %s", optarg);\r
+                       sm_id = &sm_portid;\r
+                       break;\r
+               case 't':\r
+                       timeout = strtoul(optarg, 0, 0);\r
+                       madrpc_set_timeout(timeout);\r
+                       break;\r
+               case 'v':\r
+                       madrpc_show_errors(1);\r
+                       verbose++;\r
+                       break;\r
+               case 'V':\r
+                       fprintf(stderr, "%s %s\n", argv0, get_build_version() );\r
+                       exit(-1);\r
+               default:\r
+                       usage();\r
+                       break;\r
+               }\r
+       }\r
+       argc -= optind;\r
+       argv += optind;\r
+\r
+       if (!argc)\r
+               usage();\r
+\r
+       if (argc > 1)\r
+               startlid = strtoul(argv[1], 0, 0);\r
+       if (argc > 2)\r
+               endlid = strtoul(argv[2], 0, 0);\r
+\r
+       madrpc_init(ca, ca_port, mgmt_classes, 3);\r
+\r
+       if (!argc) {\r
+               if (ib_resolve_self(&portid, 0, 0) < 0)\r
+                       IBERROR("can't resolve self addr");\r
+       } else {\r
+               if (ib_resolve_portid_str(&portid, argv[0], dest_type, sm_id) < 0)\r
+                       IBERROR("can't resolve destination port %s", argv[1]);\r
+       }\r
+\r
+       if (multicast)\r
+               err = dump_multicast_tables(&portid, startlid, endlid);\r
+       else\r
+               err = dump_unicast_tables(&portid, startlid, endlid);\r
+\r
+       if (err)\r
+               IBERROR("dump tables: %s", err);\r
+\r
+       exit(0);\r
+}\r
diff --git a/branches/winverbs/tools/infiniband_diags/src/ibsendtrap.c b/branches/winverbs/tools/infiniband_diags/src/ibsendtrap.c
new file mode 100644 (file)
index 0000000..47db29a
--- /dev/null
@@ -0,0 +1,176 @@
+/*\r
+ * Copyright (c) 2008 Lawrence Livermore National Security\r
+ *\r
+ * Produced at Lawrence Livermore National Laboratory.\r
+ * Written by Ira Weiny <weiny2@llnl.gov>.\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
+#include <stdlib.h>\r
+#include <stdio.h>\r
+#include <unistd.h>\r
+#include <string.h>\r
+\r
+#define _GNU_SOURCE\r
+#include <getopt.h>\r
+\r
+#include <infiniband/mad.h>\r
+#include <infiniband/iba/ib_types.h>\r
+\r
+#include "ibdiag_common.h"\r
+\r
+char *argv0 = "";\r
+\r
+static int send_144_node_desc_update(void)\r
+{\r
+       ib_portid_t sm_port;\r
+       ib_portid_t selfportid;\r
+       int selfport;\r
+       ib_rpc_t trap_rpc;\r
+       ib_mad_notice_attr_t notice;\r
+\r
+       if (ib_resolve_self(&selfportid, &selfport, NULL))\r
+               IBERROR("can't resolve self");\r
+\r
+       if (ib_resolve_smlid(&sm_port, 0))\r
+               IBERROR("can't resolve SM destination port");\r
+\r
+       memset(&trap_rpc, 0, sizeof(trap_rpc));\r
+       trap_rpc.mgtclass = IB_SMI_CLASS;\r
+       trap_rpc.method = IB_MAD_METHOD_TRAP;\r
+       trap_rpc.trid = mad_trid();\r
+       trap_rpc.attr.id = NOTICE;\r
+       trap_rpc.datasz = IB_SMP_DATA_SIZE;\r
+       trap_rpc.dataoffs = IB_SMP_DATA_OFFS;\r
+\r
+       memset(&notice, 0, sizeof(notice));\r
+       notice.generic_type = 0x80 | IB_NOTICE_TYPE_INFO;\r
+       notice.g_or_v.generic.prod_type_lsb = cl_hton16(IB_NODE_TYPE_CA);\r
+       notice.g_or_v.generic.trap_num = cl_hton16(144);\r
+       notice.issuer_lid = cl_hton16(selfportid.lid);\r
+       notice.data_details.ntc_144.lid = cl_hton16(selfportid.lid);\r
+       notice.data_details.ntc_144.local_changes =\r
+           TRAP_144_MASK_OTHER_LOCAL_CHANGES;\r
+       notice.data_details.ntc_144.change_flgs =\r
+           TRAP_144_MASK_NODE_DESCRIPTION_CHANGE;\r
+\r
+       return (mad_send(&trap_rpc, &sm_port, NULL, &notice));\r
+}\r
+\r
+typedef struct _trap_def {\r
+       char *trap_name;\r
+       int (*send_func) (void);\r
+} trap_def_t;\r
+\r
+trap_def_t traps[2] = {\r
+       {"node_desc_change", send_144_node_desc_update},\r
+       {NULL, NULL}\r
+};\r
+\r
+static void usage(void)\r
+{\r
+       int i;\r
+\r
+       fprintf(stderr, "Usage: %s [-hV]"\r
+               " [-C <ca_name>] [-P <ca_port>] [<trap_name>]\n", argv0);\r
+       fprintf(stderr, "   -V print version\n");\r
+       fprintf(stderr, "   <trap_name> can be one of the following\n");\r
+       for (i = 0; traps[i].trap_name; i++) {\r
+               fprintf(stderr, "      %s\n", traps[i].trap_name);\r
+       }\r
+       fprintf(stderr, "   default behavior is to send \"%s\"\n",\r
+               traps[0].trap_name);\r
+\r
+       exit(-1);\r
+}\r
+\r
+int send_trap(char *trap_name)\r
+{\r
+       int i;\r
+\r
+       for (i = 0; traps[i].trap_name; i++) {\r
+               if (strcmp(traps[i].trap_name, trap_name) == 0) {\r
+                       return (traps[i].send_func());\r
+               }\r
+       }\r
+       usage();\r
+       exit(1);\r
+}\r
+\r
+int main(int argc, char **argv)\r
+{\r
+       int mgmt_classes[2] = { IB_SMI_CLASS, IB_SMI_DIRECT_CLASS };\r
+       int ch = 0;\r
+       char *trap_name = NULL;\r
+       char *ca = NULL;\r
+       int ca_port = 0;\r
+\r
+       static char const str_opts[] = "hVP:C:";\r
+       static const struct option long_opts[] = {\r
+               {"Version", 0, 0, 'V'},\r
+               {"P", 1, 0, 'P'},\r
+               {"C", 1, 0, 'C'},\r
+               {"help", 0, 0, 'h'},\r
+               {}\r
+       };\r
+\r
+       argv0 = argv[0];\r
+\r
+       while ((ch = getopt_long(argc, argv, str_opts, long_opts, NULL)) != -1) {\r
+               switch (ch) {\r
+               case 'V':\r
+                       fprintf(stderr, "%s %s\n", argv0, get_build_version());\r
+                       exit(-1);\r
+               case 'C':\r
+                       ca = optarg;\r
+                       break;\r
+               case 'P':\r
+                       ca_port = strtoul(optarg, NULL, 0);\r
+                       break;\r
+               case 'h':\r
+               default:\r
+                       usage();\r
+               }\r
+       }\r
+       argc -= optind;\r
+       argv += optind;\r
+\r
+       if (!argv[0]) {\r
+               trap_name = traps[0].trap_name;\r
+       } else {\r
+               trap_name = argv[0];\r
+       }\r
+\r
+       madrpc_show_errors(1);\r
+       madrpc_init(ca, ca_port, mgmt_classes, 2);\r
+\r
+       return (send_trap(trap_name));\r
+}\r
diff --git a/branches/winverbs/tools/infiniband_diags/src/ibstat.c b/branches/winverbs/tools/infiniband_diags/src/ibstat.c
new file mode 100644 (file)
index 0000000..8825277
--- /dev/null
@@ -0,0 +1,297 @@
+/*\r
+ * Copyright (c) 2004-2008 Voltaire 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
+#include <stdio.h>\r
+#include <stdlib.h>\r
+\r
+#if !defined(_WIN32) \r
+#define _GNU_SOURCE\r
+\r
+#if HAVE_CONFIG_H\r
+#  include <config.h>\r
+#endif /* HAVE_CONFIG_H */\r
+\r
+#include <inttypes.h>\r
+#include <string.h>\r
+#include <errno.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <unistd.h>\r
+#include <stdarg.h>\r
+#include <sys/types.h>\r
+#include <sys/stat.h>\r
+#include <fcntl.h>\r
+#include <sys/ioctl.h>\r
+#include <unistd.h>\r
+#include <string.h>\r
+#include <getopt.h>\r
+#include <endian.h>\r
+#include <byteswap.h>\r
+#include <sys/poll.h>\r
+#include <syslog.h>\r
+#include <netinet/in.h>\r
+#else\r
+#include "..\..\..\..\etc\user\getopt.c"\r
+#endif\r
+\r
+#include <infiniband/umad.h>\r
+#include <infiniband/mad.h>\r
+#include <ibdiag_common.h>\r
+\r
+static int debug;\r
+\r
+char *argv0 = "ibstat";\r
+\r
+static char *node_type_str[] = {\r
+       "???",\r
+       "CA",\r
+       "Switch",\r
+       "Router",\r
+       "iWARP RNIC"\r
+};\r
+\r
+static void\r
+ca_dump(umad_ca_t *ca)\r
+{\r
+       if (!ca->node_type)\r
+               return;\r
+       printf("%s '%s'\n", ((unsigned int)ca->node_type <= IB_NODE_MAX ? node_type_str[ca->node_type] : "???"), ca->ca_name);\r
+       printf("\t%s type: %s\n", ((unsigned int)ca->node_type <= IB_NODE_MAX ? node_type_str[ca->node_type] : "???"),ca->ca_type);\r
+       printf("\tNumber of ports: %d\n", ca->numports);\r
+       printf("\tFirmware version: %s\n", ca->fw_ver);\r
+       printf("\tHardware version: %s\n", ca->hw_ver);\r
+       printf("\tNode GUID: 0x%016"PRIx64"\n", ntohll(ca->node_guid));\r
+       printf("\tSystem image GUID: 0x%016"PRIx64"\n", ntohll(ca->system_guid));\r
+}\r
+\r
+static char *port_state_str[] = {\r
+       "???",\r
+       "Down",\r
+       "Initializing",\r
+       "Armed",\r
+       "Active"\r
+};\r
+\r
+static char *port_phy_state_str[] = {\r
+       "No state change",\r
+       "Sleep",\r
+       "Polling",\r
+       "Disabled",\r
+       "PortConfigurationTraining",\r
+       "LinkUp",\r
+       "LinkErrorRecovery",\r
+       "PhyTest"\r
+};\r
+\r
+static int\r
+port_dump(umad_port_t *port, int alone)\r
+{\r
+       char *pre = "";\r
+       char *hdrpre = "";\r
+\r
+       if (!port)\r
+               return -1;\r
+\r
+       if (!alone) {\r
+               pre = "         ";\r
+               hdrpre = "      ";\r
+       }\r
+\r
+       printf("%sPort %d:\n", hdrpre, port->portnum);\r
+       printf("%sState: %s\n", pre, (unsigned int)port->state <= 4 ? port_state_str[port->state] : "???");\r
+       printf("%sPhysical state: %s\n", pre, (unsigned int)port->state <= 7 ? port_phy_state_str[port->phys_state] : "???");\r
+       printf("%sRate: %d\n", pre, port->rate);\r
+       printf("%sBase lid: %d\n", pre, port->base_lid);\r
+       printf("%sLMC: %d\n", pre, port->lmc);\r
+       printf("%sSM lid: %d\n", pre, port->sm_lid);\r
+       printf("%sCapability mask: 0x%08x\n", pre, (unsigned int)ntohll(port->capmask));\r
+       printf("%sPort GUID: 0x%016"PRIx64"\n", pre, (long long unsigned)ntohll(port->port_guid));\r
+       return 0;\r
+}\r
+\r
+static int\r
+ca_stat(char *ca_name, int portnum, int no_ports)\r
+{\r
+       umad_ca_t ca;\r
+       int r;\r
+\r
+       if ((r = umad_get_ca(ca_name, &ca)) < 0)\r
+               return r;\r
+\r
+       if (!ca.node_type)\r
+               return 0;\r
+\r
+       if (!no_ports && portnum >= 0) {\r
+               if (portnum > ca.numports || !ca.ports[portnum]) {\r
+                       IBWARN("%s: '%s' has no port number %d - max (%d)",\r
+                               ((unsigned int)ca.node_type <= IB_NODE_MAX ? node_type_str[ca.node_type] : "???"),\r
+                               ca_name, portnum, ca.numports);\r
+                       return -1;\r
+               }\r
+               printf("%s: '%s'\n", ((unsigned int)ca.node_type <= IB_NODE_MAX ? node_type_str[ca.node_type] : "???"), ca.ca_name);\r
+               port_dump(ca.ports[portnum], 1);\r
+               return 0;\r
+       }\r
+\r
+       /* print ca header */\r
+       ca_dump(&ca);\r
+\r
+       if (no_ports)\r
+               return 0;\r
+\r
+       for (portnum = 0; portnum < ca.numports; portnum++)\r
+               port_dump(ca.ports[portnum], 0);\r
+\r
+       return 0;\r
+}\r
+\r
+static int\r
+ports_list(char names[][UMAD_CA_NAME_LEN], int n)\r
+{\r
+       uint64_t guids[64];\r
+       int found, ports, i;\r
+\r
+       for (i = 0, found = 0; i < n && found < 64; i++) {\r
+               if ((ports = umad_get_ca_portguids(names[i], guids + found, 64 - found)) < 0)\r
+                       return -1;\r
+               found += ports;\r
+       }\r
+\r
+       for (i = 0; i < found; i++)\r
+               if (guids[i])\r
+                       printf("0x%016"PRIx64"\n", (long long unsigned)ntohll(guids[i]));\r
+       return found;\r
+}\r
+\r
+void\r
+usage(void)\r
+{\r
+       fprintf(stderr, "Usage: %s [-d(ebug) -l(ist_of_cas) -s(hort) -p(ort_list) -V(ersion)] <ca_name> [portnum]\n", argv0);\r
+       fprintf(stderr, "\tExamples:\n");\r
+       fprintf(stderr, "\t\t%s -l        # list all IB devices\n", argv0);\r
+       fprintf(stderr, "\t\t%s mthca0 2 # stat port 2 of 'mthca0'\n", argv0);\r
+       exit(-1);\r
+}\r
+\r
+int __cdecl\r
+main(int argc, char *argv[])\r
+{\r
+       char names[20][UMAD_CA_NAME_LEN];\r
+       int dev_port = -1;\r
+       int list_only = 0, short_format = 0, list_ports = 0;\r
+       int n, i;\r
+\r
+       static char str_opts[] = "dlspVhu";\r
+       static struct option long_opts[] = {\r
+               { "debug", 0, 0, 'd'},\r
+               { "list_of_cas", 0, 0, 'l'},\r
+               { "short", 0, 0, 's'},\r
+               { "port_list", 0, 0, 'p'},\r
+               { "Version", 0, 0, 'V'},\r
+               { "help", 0, 0, 'h'},\r
+               { "usage", 0, 0, 'u'},\r
+               { 0 }\r
+       };\r
+\r
+       argv0 = argv[0];\r
+\r
+       while (1) {\r
+               int ch = getopt_long(argc, argv, str_opts, long_opts, NULL);\r
+               if ( ch == -1 )\r
+                       break;\r
+               switch(ch) {\r
+               case 'd':\r
+                       debug++;\r
+                       break;\r
+               case 'l':\r
+                       list_only++;\r
+                       break;\r
+               case 's':\r
+                       short_format++;\r
+                       break;\r
+               case 'p':\r
+                       list_ports++;\r
+                       break;\r
+               case 'V':\r
+                       fprintf(stderr, "%s %s\n", argv0, get_build_version() );\r
+                       exit(-1);\r
+               default:\r
+                       usage();\r
+                       break;\r
+               }\r
+       }\r
+       argc -= optind;\r
+       argv += optind;\r
+\r
+       if (argc > 1)\r
+               dev_port = strtol(argv[1], 0, 0);\r
+\r
+       if (umad_init() < 0)\r
+               IBPANIC("can't init UMAD library");\r
+\r
+       if ((n = umad_get_cas_names((void *)names, UMAD_CA_NAME_LEN)) < 0)\r
+               IBPANIC("can't list IB device names");\r
+\r
+       if (argc) {\r
+               for (i = 0; i < n; i++)\r
+                       if (!strncmp(names[i], argv[0], sizeof names[i]))\r
+                               break;\r
+               if (i >= n)\r
+                       IBPANIC("'%s' IB device can't be found", argv[0]);\r
+\r
+               strncpy(names[i], argv[0], sizeof names[i]);\r
+               n = 1;\r
+       }\r
+\r
+       if (list_ports) {\r
+               if (ports_list(names, n) < 0)\r
+                       IBPANIC("can't list ports");\r
+               return 0;\r
+       }\r
+\r
+       if (!list_only && argc) {\r
+               if (ca_stat(argv[0], dev_port, short_format) < 0)\r
+                       IBPANIC("stat of IB device '%s' failed", argv[0]);\r
+               return 0;\r
+       }\r
+\r
+       for (i = 0; i < n; i++) {\r
+               if (list_only)\r
+                       printf("%s\n", names[i]);\r
+               else\r
+                       if (ca_stat(names[i], -1, short_format) < 0)\r
+                               IBPANIC("stat of IB device '%s' failed", names[i]);\r
+       }\r
+\r
+       return 0;\r
+}\r
diff --git a/branches/winverbs/tools/infiniband_diags/src/ibstat/SOURCES b/branches/winverbs/tools/infiniband_diags/src/ibstat/SOURCES
new file mode 100644 (file)
index 0000000..4fc625f
--- /dev/null
@@ -0,0 +1,32 @@
+TARGETNAME = ibstat\r
+TARGETPATH = ..\..\..\..\bin\user\obj$(BUILD_ALT_DIR)\r
+TARGETTYPE = PROGRAM\r
+\r
+UMTYPE = console\r
+UMENTRY = main\r
+\r
+USE_MSVCRT = 1\r
+USE_STL = 1\r
+USE_NATIVE_EH = 1\r
+USE_IOSTREAM = 1\r
+\r
+SOURCES = ..\ibstat.c ..\ibdiag_common.c\r
+       \r
+INCLUDES = ..;..\..\include;..\..\..\..\ulp\libibmad\include;..\..\..\..\ulp\libibumad\include;..\..\..\..\inc;..\..\..\..\inc\user;\r
+\r
+TARGETLIBS =   \\r
+       $(SDK_LIB_PATH)\kernel32.lib    \\r
+       $(SDK_LIB_PATH)\advapi32.lib    \\r
+       $(SDK_LIB_PATH)\user32.lib      \\r
+       $(SDK_LIB_PATH)\ole32.lib       \\r
+       $(SDK_LIB_PATH)\ws2_32.lib      \\r
+!if $(FREEBUILD)\r
+       $(TARGETPATH)\*\complib.lib     \\r
+       $(TARGETPATH)\*\libibmad.lib    \\r
+       $(TARGETPATH)\*\libibumad.lib   \r
+!else\r
+       $(TARGETPATH)\*\complibd.lib    \\r
+       $(TARGETPATH)\*\libibmadd.lib   \\r
+       $(TARGETPATH)\*\libibumadd.lib  \r
+!endif\r
+\r
diff --git a/branches/winverbs/tools/infiniband_diags/src/ibsysstat.c b/branches/winverbs/tools/infiniband_diags/src/ibsysstat.c
new file mode 100644 (file)
index 0000000..63e450c
--- /dev/null
@@ -0,0 +1,354 @@
+/*\r
+ * Copyright (c) 2004-2008 Voltaire 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
+#if HAVE_CONFIG_H\r
+#  include <config.h>\r
+#endif /* HAVE_CONFIG_H */\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <unistd.h>\r
+#include <stdarg.h>\r
+#include <time.h>\r
+#include <string.h>\r
+#include <getopt.h>\r
+\r
+#include <infiniband/common.h>\r
+#include <infiniband/umad.h>\r
+#include <infiniband/mad.h>\r
+\r
+#include "ibdiag_common.h"\r
+\r
+#undef DEBUG\r
+#define        DEBUG   if (verbose) IBWARN\r
+\r
+static int dest_type = IB_DEST_LID;\r
+static int verbose;\r
+\r
+#define MAX_CPUS 8\r
+\r
+enum ib_sysstat_attr_t {\r
+       IB_PING_ATTR = 0x10,\r
+       IB_HOSTINFO_ATTR = 0x11,\r
+       IB_CPUINFO_ATTR = 0x12,\r
+};\r
+\r
+typedef struct cpu_info {\r
+       char *model;\r
+       char *mhz;\r
+} cpu_info;\r
+\r
+static cpu_info cpus[MAX_CPUS];\r
+static int host_ncpu;\r
+\r
+char *argv0 = "ibsysstat";\r
+\r
+static void\r
+mk_reply(int attr, void *data, int sz)\r
+{\r
+       char *s = data;\r
+       int n, i;\r
+\r
+       switch (attr) {\r
+       case IB_PING_ATTR:\r
+               break;          /* nothing to do here, just reply */\r
+       case IB_HOSTINFO_ATTR:\r
+               if (gethostname(s, sz) < 0)\r
+                       snprintf(s, sz, "?hostname?");\r
+               s[sz-1] = 0;\r
+               if ((n = strlen(s)) >= sz)\r
+                       break;\r
+               s[n] = '.';\r
+               s += n+1;\r
+               sz -= n+1;\r
+               if (getdomainname(s, sz) < 0)\r
+                       snprintf(s, sz, "?domainname?");\r
+               if (strlen(s) == 0)\r
+                       s[-1] = 0;      /* no domain */\r
+               break;\r
+       case IB_CPUINFO_ATTR:\r
+               for (i = 0; i < host_ncpu && sz > 0; i++) {\r
+                       n = snprintf(s, sz, "cpu %d: model %s MHZ %s\n",\r
+                                    i, cpus[i].model, cpus[i].mhz);\r
+                       if (n >= sz) {\r
+                               IBWARN("cpuinfo truncated");\r
+                               break;\r
+                       }\r
+                       sz -= n;\r
+                       s += n;\r
+               }\r
+               break;\r
+       default:\r
+               DEBUG("unknown attr %d", attr);\r
+       }\r
+}\r
+\r
+static char *\r
+ibsystat_serv(void)\r
+{\r
+       void *umad;\r
+       void *mad;\r
+       int attr, mod;\r
+\r
+       DEBUG("starting to serve...");\r
+\r
+       while ((umad = mad_receive(0, -1))) {\r
+\r
+               mad = umad_get_mad(umad);\r
+\r
+               attr = mad_get_field(mad, 0, IB_MAD_ATTRID_F);\r
+               mod = mad_get_field(mad, 0, IB_MAD_ATTRMOD_F);\r
+\r
+               DEBUG("got packet: attr 0x%x mod 0x%x", attr, mod);\r
+\r
+               mk_reply(attr, (char *)mad + IB_VENDOR_RANGE2_DATA_OFFS, IB_VENDOR_RANGE2_DATA_SIZE);\r
+\r
+               if (mad_respond(umad, 0, 0) < 0)\r
+                       DEBUG("respond failed");\r
+\r
+               mad_free(umad);\r
+       }\r
+\r
+       DEBUG("server out");\r
+       return 0;\r
+}\r
+\r
+static int\r
+match_attr(char *str)\r
+{\r
+       if (!strcmp(str, "ping"))\r
+               return IB_PING_ATTR;\r
+       if (!strcmp(str, "host"))\r
+               return IB_HOSTINFO_ATTR;\r
+       if (!strcmp(str, "cpu"))\r
+               return IB_CPUINFO_ATTR;\r
+       return -1;\r
+}\r
+\r
+static char *\r
+ibsystat(ib_portid_t *portid, int attr)\r
+{\r
+       char data[IB_VENDOR_RANGE2_DATA_SIZE] = {0};\r
+       ib_vendor_call_t call;\r
+\r
+       DEBUG("Sysstat ping..");\r
+\r
+       call.method = IB_MAD_METHOD_GET;\r
+       call.mgmt_class = IB_VENDOR_OPENIB_SYSSTAT_CLASS;\r
+       call.attrid = attr;\r
+       call.mod = 0;\r
+       call.oui = IB_OPENIB_OUI;\r
+       call.timeout = 0;\r
+       memset(&call.rmpp, 0, sizeof call.rmpp);\r
+\r
+       if (!ib_vendor_call(data, portid, &call))\r
+               return "vendor call failed";\r
+\r
+       DEBUG("Got sysstat pong..");\r
+       if (attr != IB_PING_ATTR)\r
+               puts(data);\r
+       else\r
+               printf("sysstat ping succeeded\n");\r
+       return 0;\r
+}\r
+\r
+int\r
+build_cpuinfo(void)\r
+{\r
+       char line[1024] = {0}, *s, *e;\r
+       FILE *f;\r
+       int ncpu = 0;\r
+\r
+       if (!(f = fopen("/proc/cpuinfo", "r"))) {\r
+               IBWARN("couldn't open /proc/cpuinfo");\r
+               return 0;\r
+       }\r
+\r
+       while (fgets(line, sizeof(line) - 1, f)) {\r
+               if (!strncmp(line, "processor\t", 10)) {\r
+                       ncpu++;\r
+                       if (ncpu > MAX_CPUS)\r
+                               return MAX_CPUS;\r
+                       continue;\r
+               }\r
+\r
+               if (!ncpu || !(s = strchr(line, ':')))\r
+                       continue;\r
+\r
+               if ((e = strchr(s, '\n')))\r
+                       *e = 0;\r
+               if (!strncmp(line, "model name\t", 11))\r
+                       cpus[ncpu-1].model = strdup(s+1);\r
+               else if (!strncmp(line, "cpu MHz\t", 8))\r
+                       cpus[ncpu-1].mhz = strdup(s+1);\r
+       }\r
+\r
+       fclose(f);\r
+\r
+       DEBUG("ncpu %d", ncpu);\r
+\r
+       return ncpu;\r
+}\r
+\r
+static void\r
+usage(void)\r
+{\r
+       char *basename;\r
+\r
+       if (!(basename = strrchr(argv0, '/')))\r
+               basename = argv0;\r
+       else\r
+               basename++;\r
+\r
+       fprintf(stderr, "Usage: %s [-d(ebug) -e(rr_show) -v(erbose) -G(uid) -s smlid -V(ersion) -C ca_name -P ca_port "\r
+                       "-t(imeout) timeout_ms -o oui -S(erver)] <dest lid|guid> [<op>]\n",\r
+                       basename);\r
+       exit(-1);\r
+}\r
+\r
+int\r
+main(int argc, char **argv)\r
+{\r
+       int mgmt_classes[3] = {IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS};\r
+       int sysstat_class = IB_VENDOR_OPENIB_SYSSTAT_CLASS;\r
+       ib_portid_t portid = {0};\r
+       ib_portid_t *sm_id = 0, sm_portid = {0};\r
+       int timeout = 0, udebug = 0, server = 0;\r
+       int oui = IB_OPENIB_OUI, attr = IB_PING_ATTR;\r
+       extern int ibdebug;\r
+       char *err;\r
+       char *ca = 0;\r
+       int ca_port = 0;\r
+\r
+       static char const str_opts[] = "C:P:t:s:o:devGSVhu";\r
+       static const struct option long_opts[] = {\r
+               { "C", 1, 0, 'C'},\r
+               { "P", 1, 0, 'P'},\r
+               { "debug", 0, 0, 'd'},\r
+               { "err_show", 0, 0, 'e'},\r
+               { "verbose", 0, 0, 'v'},\r
+               { "Guid", 0, 0, 'G'},\r
+               { "timeout", 1, 0, 't'},\r
+               { "s", 1, 0, 's'},\r
+               { "o", 1, 0, 'o'},\r
+               { "Server", 0, 0, 'S'},\r
+               { "Version", 0, 0, 'V'},\r
+               { "help", 0, 0, 'h'},\r
+               { "usage", 0, 0, 'u'},\r
+               { }\r
+       };\r
+\r
+       argv0 = argv[0];\r
+\r
+       while (1) {\r
+               int ch = getopt_long(argc, argv, str_opts, long_opts, NULL);\r
+               if ( ch == -1 )\r
+                       break;\r
+               switch(ch) {\r
+               case 'C':\r
+                       ca = optarg;\r
+                       break;\r
+               case 'P':\r
+                       ca_port = strtoul(optarg, 0, 0);\r
+                       break;\r
+               case 'd':\r
+                       ibdebug++;\r
+                       madrpc_show_errors(1);\r
+                       umad_debug(udebug);\r
+                       udebug++;\r
+                       break;\r
+               case 'e':\r
+                       madrpc_show_errors(1);\r
+                       break;\r
+               case 'G':\r
+                       dest_type = IB_DEST_GUID;\r
+                       break;\r
+               case 'o':\r
+                       oui = strtoul(optarg, 0, 0);\r
+                       break;\r
+               case 's':\r
+                       if (ib_resolve_portid_str(&sm_portid, optarg, IB_DEST_LID, 0) < 0)\r
+                               IBERROR("can't resolve SM destination port %s", optarg);\r
+                       sm_id = &sm_portid;\r
+                       break;\r
+               case 'S':\r
+                       server++;\r
+                       break;\r
+               case 't':\r
+                       timeout = strtoul(optarg, 0, 0);\r
+                       madrpc_set_timeout(timeout);\r
+                       break;\r
+               case 'v':\r
+                       verbose++;\r
+                       break;\r
+               case 'V':\r
+                       fprintf(stderr, "%s %s\n", argv0, get_build_version() );\r
+                       exit(-1);\r
+               default:\r
+                       usage();\r
+                       break;\r
+               }\r
+       }\r
+       argc -= optind;\r
+       argv += optind;\r
+\r
+       if (!argc && !server)\r
+               usage();\r
+\r
+       if (argc > 1 && (attr = match_attr(argv[1])) < 0)\r
+               usage();\r
+\r
+       madrpc_init(ca, ca_port, mgmt_classes, 3);\r
+\r
+       if (server) {\r
+               if (mad_register_server(sysstat_class, 0, 0, oui) < 0)\r
+                       IBERROR("can't serve class %d", sysstat_class);\r
+\r
+               host_ncpu = build_cpuinfo();\r
+\r
+               if ((err = ibsystat_serv()))\r
+                       IBERROR("ibssystat to %s: %s", portid2str(&portid), err);\r
+               exit(0);\r
+       }\r
+\r
+       if (mad_register_client(sysstat_class, 0) < 0)\r
+               IBERROR("can't register to sysstat class %d", sysstat_class);\r
+\r
+       if (ib_resolve_portid_str(&portid, argv[0], dest_type, sm_id) < 0)\r
+               IBERROR("can't resolve destination port %s", argv[0]);\r
+\r
+       if ((err = ibsystat(&portid, attr)))\r
+               IBERROR("ibsystat to %s: %s", portid2str(&portid), err);\r
+\r
+       exit(0);\r
+}\r
diff --git a/branches/winverbs/tools/infiniband_diags/src/ibtracert.c b/branches/winverbs/tools/infiniband_diags/src/ibtracert.c
new file mode 100644 (file)
index 0000000..724ac80
--- /dev/null
@@ -0,0 +1,865 @@
+/*\r
+ * Copyright (c) 2004-2008 Voltaire 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
+#if HAVE_CONFIG_H\r
+#  include <config.h>\r
+#endif /* HAVE_CONFIG_H */\r
+\r
+#define _GNU_SOURCE\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <unistd.h>\r
+#include <stdarg.h>\r
+#include <ctype.h>\r
+#include <getopt.h>\r
+#include <netinet/in.h>\r
+#include <inttypes.h>\r
+#include <errno.h>\r
+\r
+#include <infiniband/common.h>\r
+#include <infiniband/umad.h>\r
+#include <infiniband/mad.h>\r
+#include <infiniband/complib/cl_nodenamemap.h>\r
+\r
+#include "ibdiag_common.h"\r
+\r
+#define MAXHOPS        63\r
+\r
+static char *node_type_str[] = {\r
+       "???",\r
+       "ca",\r
+       "switch",\r
+       "router",\r
+       "iwarp rnic"\r
+};\r
+\r
+static int timeout = 0;                /* ms */\r
+static int verbose;\r
+static int force;\r
+static FILE *f;\r
+\r
+char *argv0 = "ibtracert";\r
+\r
+static char *node_name_map_file = NULL;\r
+static nn_map_t *node_name_map = NULL;\r
+\r
+typedef struct Port Port;\r
+typedef struct Switch Switch;\r
+typedef struct Node Node;\r
+\r
+struct Port {\r
+       Port *next;\r
+       Port *remoteport;\r
+       uint64_t portguid;\r
+       int portnum;\r
+       int lid;\r
+       int lmc;\r
+       int state;\r
+       int physstate;\r
+       char portinfo[64];\r
+};\r
+\r
+struct Switch {\r
+       int linearcap;\r
+       int mccap;\r
+       int linearFDBtop;\r
+       int fdb_base;\r
+       int8_t fdb[64];\r
+       char switchinfo[64];\r
+};\r
+\r
+struct Node {\r
+       Node *htnext;\r
+       Node *dnext;\r
+       Port *ports;\r
+       ib_portid_t path;\r
+       int type;\r
+       int dist;\r
+       int numports;\r
+       int upport;\r
+       Node *upnode;\r
+       uint64_t nodeguid;      /* also portguid */\r
+       char nodedesc[64];\r
+       char nodeinfo[64];\r
+};\r
+\r
+Node *nodesdist[MAXHOPS];\r
+uint64_t target_portguid;\r
+\r
+static int\r
+get_node(Node *node, Port *port, ib_portid_t *portid)\r
+{\r
+       void *pi = port->portinfo, *ni = node->nodeinfo, *nd = node->nodedesc;\r
+       char *s, *e;\r
+\r
+       if (!smp_query(ni, portid, IB_ATTR_NODE_INFO, 0, timeout))\r
+               return -1;\r
+\r
+       if (!smp_query(nd, portid, IB_ATTR_NODE_DESC, 0, timeout))\r
+               return -1;\r
+\r
+       for (s = nd, e = s + 64; s < e; s++) {\r
+               if (!*s)\r
+                       break;\r
+               if (!isprint(*s))\r
+                       *s = ' ';\r
+       }\r
+\r
+       if (!smp_query(pi, portid, IB_ATTR_PORT_INFO, 0, timeout))\r
+               return -1;\r
+\r
+       mad_decode_field(ni, IB_NODE_GUID_F, &node->nodeguid);\r
+       mad_decode_field(ni, IB_NODE_TYPE_F, &node->type);\r
+       mad_decode_field(ni, IB_NODE_NPORTS_F, &node->numports);\r
+\r
+       mad_decode_field(ni, IB_NODE_PORT_GUID_F, &port->portguid);\r
+       mad_decode_field(ni, IB_NODE_LOCAL_PORT_F, &port->portnum);\r
+       mad_decode_field(pi, IB_PORT_LID_F, &port->lid);\r
+       mad_decode_field(pi, IB_PORT_LMC_F, &port->lmc);\r
+       mad_decode_field(pi, IB_PORT_STATE_F, &port->state);\r
+\r
+       DEBUG("portid %s: got node %" PRIx64 " '%s'", portid2str(portid), node->nodeguid, node->nodedesc);\r
+       return 0;\r
+}\r
+\r
+static int\r
+switch_lookup(Switch *sw, ib_portid_t *portid, int lid)\r
+{\r
+       void *si = sw->switchinfo, *fdb = sw->fdb;\r
+\r
+       if (!smp_query(si, portid, IB_ATTR_SWITCH_INFO, 0, timeout))\r
+               return -1;\r
+\r
+       mad_decode_field(si, IB_SW_LINEAR_FDB_CAP_F, &sw->linearcap);\r
+       mad_decode_field(si, IB_SW_LINEAR_FDB_TOP_F, &sw->linearFDBtop);\r
+\r
+       if (lid > sw->linearcap && lid > sw->linearFDBtop)\r
+               return -1;\r
+\r
+       if (!smp_query(fdb, portid, IB_ATTR_LINEARFORWTBL, lid / 64, timeout))\r
+               return -1;\r
+\r
+       DEBUG("portid %s: forward lid %d to port %d",\r
+               portid2str(portid), lid, sw->fdb[lid % 64]);\r
+       return sw->fdb[lid % 64];\r
+}\r
+\r
+static int\r
+sameport(Port *a, Port *b)\r
+{\r
+       return a->portguid == b->portguid || (force && a->lid == b->lid);\r
+}\r
+\r
+static int\r
+extend_dpath(ib_dr_path_t *path, int nextport)\r
+{\r
+       if (path->cnt+2 >= sizeof(path->p))\r
+               return -1;\r
+       ++path->cnt;\r
+       path->p[path->cnt] = nextport;\r
+       return path->cnt;\r
+}\r
+\r
+static void\r
+dump_endnode(int dump, char *prompt, Node *node, Port *port)\r
+{\r
+       char *nodename = NULL;\r
+\r
+       if (!dump)\r
+               return;\r
+       if (dump == 1) {\r
+               fprintf(f, "%s {0x%016" PRIx64 "}[%d]\n",\r
+                       prompt, node->nodeguid,\r
+                       node->type == IB_NODE_SWITCH ? 0 : port->portnum);\r
+               return;\r
+       }\r
+\r
+       nodename = remap_node_name(node_name_map, node->nodeguid, node->nodedesc);\r
+\r
+       fprintf(f, "%s %s {0x%016" PRIx64 "} portnum %d lid %u-%u \"%s\"\n",\r
+               prompt,\r
+               (node->type <= IB_NODE_MAX ? node_type_str[node->type] : "???"),\r
+               node->nodeguid, node->type == IB_NODE_SWITCH ? 0 : port->portnum,\r
+               port->lid, port->lid + (1 << port->lmc) - 1,\r
+               nodename);\r
+\r
+       free(nodename);\r
+}\r
+\r
+static void\r
+dump_route(int dump, Node *node, int outport, Port *port)\r
+{\r
+       char *nodename = NULL;\r
+\r
+       if (!dump && !verbose)\r
+               return;\r
+\r
+       nodename = remap_node_name(node_name_map, node->nodeguid, node->nodedesc);\r
+\r
+       if (dump == 1)\r
+               fprintf(f, "[%d] -> {0x%016" PRIx64 "}[%d]\n",\r
+                       outport, port->portguid, port->portnum);\r
+       else\r
+               fprintf(f, "[%d] -> %s port {0x%016" PRIx64 "}[%d] lid %u-%u \"%s\"\n",\r
+                       outport,\r
+                       (node->type <= IB_NODE_MAX ? node_type_str[node->type] : "???"),\r
+                       port->portguid, port->portnum,\r
+                       port->lid, port->lid + (1 << port->lmc) - 1,\r
+                       nodename);\r
+\r
+       free(nodename);\r
+}\r
+\r
+static int\r
+find_route(ib_portid_t *from, ib_portid_t *to, int dump)\r
+{\r
+       Node *node, fromnode, tonode, nextnode;\r
+       Port *port, fromport, toport, nextport;\r
+       Switch sw;\r
+       int maxhops = MAXHOPS;\r
+       int portnum, outport;\r
+\r
+       DEBUG("from %s", portid2str(from));\r
+\r
+       if (get_node(&fromnode, &fromport, from) < 0 ||\r
+           get_node(&tonode, &toport, to) < 0) {\r
+               IBWARN("can't reach to/from ports");\r
+               if (!force)\r
+                       return -1;\r
+               if (to->lid > 0)\r
+                       toport.lid = to->lid;\r
+               IBWARN("Force: look for lid %d", to->lid);\r
+       }\r
+\r
+       node = &fromnode;\r
+       port = &fromport;\r
+       portnum = port->portnum;\r
+\r
+       dump_endnode(dump, "From", node, port);\r
+\r
+       while (maxhops--) {\r
+               if (port->state != 4)\r
+                       goto badport;\r
+\r
+               if (sameport(port, &toport))\r
+                       break;  /* found */\r
+\r
+               outport = portnum;\r
+               if (node->type == IB_NODE_SWITCH) {\r
+                       DEBUG("switch node");\r
+                       if ((outport = switch_lookup(&sw, from, to->lid)) < 0 ||\r
+                           outport > node->numports)\r
+                               goto badtbl;\r
+\r
+                       if (extend_dpath(&from->drpath, outport) < 0)\r
+                               goto badpath;\r
+\r
+                       if (get_node(&nextnode, &nextport, from) < 0) {\r
+                               IBWARN("can't reach port at %s", portid2str(from));\r
+                               return -1;\r
+                       }\r
+                       if (outport == 0) {\r
+                               if (!sameport(&nextport, &toport))\r
+                                       goto badtbl;\r
+                               else\r
+                                       break;  /* found SMA port */\r
+                       }\r
+               } else if ((node->type == IB_NODE_CA) ||\r
+                          (node->type == IB_NODE_ROUTER)) {\r
+                       int ca_src = 0;\r
+\r
+                       DEBUG("ca or router node");\r
+                       if (!sameport(port, &fromport)) {\r
+                               IBWARN("can't continue: reached CA or router port %" PRIx64 ", lid %d",\r
+                                       port->portguid, port->lid);\r
+                               return -1;\r
+                       }\r
+                       /* we are at CA or router "from" - go one hop back to (hopefully) a switch */\r
+                       if (from->drpath.cnt > 0) {\r
+                               DEBUG("ca or router node - return back 1 hop");\r
+                               from->drpath.cnt--;\r
+                       } else {\r
+                               ca_src = 1;\r
+                               if (portnum && extend_dpath(&from->drpath, portnum) < 0)\r
+                                       goto badpath;\r
+                       }\r
+                       if (get_node(&nextnode, &nextport, from) < 0) {\r
+                               IBWARN("can't reach port at %s", portid2str(from));\r
+                               return -1;\r
+                       }\r
+                       /* fix port num to be seen from the CA or router side */\r
+                       if (!ca_src)\r
+                               nextport.portnum = from->drpath.p[from->drpath.cnt+1];\r
+               }\r
+               port = &nextport;\r
+               if (port->state != 4)\r
+                       goto badoutport;\r
+               node = &nextnode;\r
+               portnum = port->portnum;\r
+               dump_route(dump, node, outport, port);\r
+       }\r
+\r
+       if (maxhops <= 0) {\r
+               IBWARN("no route found after %d hops", MAXHOPS);\r
+               return -1;\r
+       }\r
+       dump_endnode(dump, "To", node, port);\r
+       return 0;\r
+\r
+badport:\r
+       IBWARN("Bad port state found: node \"%s\" port %d state %d",\r
+               clean_nodedesc(node->nodedesc), portnum, port->state);\r
+       return -1;\r
+badoutport:\r
+       IBWARN("Bad out port state found: node \"%s\" outport %d state %d",\r
+               clean_nodedesc(node->nodedesc), outport, port->state);\r
+       return -1;\r
+badtbl:\r
+       IBWARN("Bad forwarding table entry found at: node \"%s\" lid entry %d is %d (top %d)",\r
+               clean_nodedesc(node->nodedesc), to->lid, outport, sw.linearFDBtop);\r
+       return -1;\r
+badpath:\r
+       IBWARN("Direct path too long!");\r
+       return -1;\r
+}\r
+\r
+\r
+/**************************\r
+ * MC span part\r
+ */\r
+\r
+#define HASHGUID(guid)         ((uint32_t)(((uint32_t)(guid) * 101) ^ ((uint32_t)((guid) >> 32) * 103)))\r
+#define HTSZ 137\r
+\r
+static int\r
+insert_node(Node *new)\r
+{\r
+       static Node *nodestbl[HTSZ];\r
+       int hash = HASHGUID(new->nodeguid) % HTSZ;\r
+       Node *node ;\r
+\r
+       for (node = nodestbl[hash]; node; node = node->htnext)\r
+               if (node->nodeguid == new->nodeguid) {\r
+                       DEBUG("node %" PRIx64 " already exists", new->nodeguid);\r
+                       return -1;\r
+               }\r
+\r
+       new->htnext = nodestbl[hash];\r
+       nodestbl[hash] = new;\r
+\r
+       return 0;\r
+}\r
+\r
+static int\r
+get_port(Port *port, int portnum, ib_portid_t *portid)\r
+{\r
+       char portinfo[64];\r
+       void *pi = portinfo;\r
+\r
+       port->portnum = portnum;\r
+\r
+       if (!smp_query(pi, portid, IB_ATTR_PORT_INFO, portnum, timeout))\r
+               return -1;\r
+\r
+       mad_decode_field(pi, IB_PORT_LID_F, &port->lid);\r
+       mad_decode_field(pi, IB_PORT_LMC_F, &port->lmc);\r
+       mad_decode_field(pi, IB_PORT_STATE_F, &port->state);\r
+       mad_decode_field(pi, IB_PORT_PHYS_STATE_F, &port->physstate);\r
+\r
+       VERBOSE("portid %s portnum %d: lid %d state %d physstate %d",\r
+               portid2str(portid), portnum, port->lid, port->state, port->physstate);\r
+       return 1;\r
+}\r
+\r
+static void\r
+link_port(Port *port, Node *node)\r
+{\r
+       port->next = node->ports;\r
+       node->ports = port;\r
+}\r
+\r
+static int\r
+new_node(Node *node, Port *port, ib_portid_t *path, int dist)\r
+{\r
+       if (port->portguid == target_portguid) {\r
+               node->dist = -1;                /* tag as target */\r
+               link_port(port, node);\r
+               dump_endnode(verbose, "found target", node, port);\r
+               return 1;       /* found; */\r
+       }\r
+\r
+       /* BFS search start with my self */\r
+       if (insert_node(node) < 0)\r
+               return -1;      /* known switch */\r
+\r
+       VERBOSE("insert dist %d node %p port %d lid %d", dist, node, port->portnum, port->lid);\r
+\r
+       link_port(port, node);\r
+\r
+       node->dist = dist;\r
+       node->path = *path;\r
+       node->dnext = nodesdist[dist];\r
+       nodesdist[dist] = node;\r
+\r
+       return 0;\r
+}\r
+\r
+static int\r
+switch_mclookup(Node *node, ib_portid_t *portid, int mlid, char *map)\r
+{\r
+       Switch sw;\r
+       char mdb[64];\r
+       void *si = sw.switchinfo;\r
+       uint16_t *msets = (uint16_t *)mdb;\r
+       int maxsets, block, i, set;\r
+\r
+       memset(map, 0, 256);\r
+\r
+       if (!smp_query(si, portid, IB_ATTR_SWITCH_INFO, 0, timeout))\r
+               return -1;\r
+\r
+       mlid -= 0xc000;\r
+\r
+       mad_decode_field(si, IB_SW_MCAST_FDB_CAP_F, &sw.mccap);\r
+\r
+       if (mlid > sw.mccap)\r
+               return -1;\r
+\r
+       block = mlid / 32;\r
+       maxsets = (node->numports + 15) / 16;           /* round up */\r
+\r
+       for (set = 0; set < maxsets; set++) {\r
+               if (!smp_query(mdb, portid, IB_ATTR_MULTICASTFORWTBL,\r
+                   block | (set << 28), timeout))\r
+                       return -1;\r
+\r
+               for (i = 0; i < 16; i++, map++) {\r
+                       uint16_t mask = ntohs(msets[mlid % 32]);\r
+                       if (mask & (1 << i))\r
+                               *map = 1;\r
+                       else\r
+                               continue;\r
+                       VERBOSE("Switch guid 0x%" PRIx64 ": mlid 0x%x is forwarded to port %d",\r
+                               node->nodeguid, mlid + 0xc000, i + set * 16);\r
+               }\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+/*\r
+ * Return 1 if found, 0 if not, -1 on errors.\r
+ */\r
+static Node *\r
+find_mcpath(ib_portid_t *from, int mlid)\r
+{\r
+       Node *node, *remotenode;\r
+       Port *port, *remoteport;\r
+       char map[256];\r
+       int r, i;\r
+       int dist = 0, leafport = 0;\r
+       ib_portid_t *path;\r
+\r
+       DEBUG("from %s", portid2str(from));\r
+\r
+       if (!(node = calloc(1, sizeof(Node))))\r
+               IBERROR("out of memory");\r
+\r
+       if (!(port = calloc(1, sizeof(Port))))\r
+               IBERROR("out of memory");\r
+\r
+       if (get_node(node, port, from) < 0) {\r
+               IBWARN("can't reach node %s", portid2str(from));\r
+               return 0;\r
+       }\r
+\r
+       node->upnode = 0;               /* root */\r
+       if ((r = new_node(node, port, from, 0)) > 0) {\r
+               if (node->type != IB_NODE_SWITCH) {\r
+                       IBWARN("ibtracert from CA to CA is unsupported");\r
+                       return 0;       /* ibtracert from host to itself is unsupported */\r
+               }\r
+\r
+               if (switch_mclookup(node, from, mlid, map) < 0 ||\r
+                   !map[0])\r
+                       return 0;\r
+               return node;\r
+       }\r
+\r
+       for (dist = 0; dist < MAXHOPS; dist++) {\r
+\r
+               for (node = nodesdist[dist]; node; node = node->dnext) {\r
+\r
+                       path = &node->path;\r
+\r
+                       VERBOSE("dist %d node %p", dist, node);\r
+                       dump_endnode(verbose, "processing", node, node->ports);\r
+\r
+                       memset(map, 0, sizeof(map));\r
+\r
+                       if (node->type != IB_NODE_SWITCH) {\r
+                               if (dist)\r
+                                       continue;\r
+                               leafport = path->drpath.p[path->drpath.cnt];\r
+                               map[port->portnum] = 1;\r
+                               node->upport = 0;       /* starting here */\r
+                               DEBUG("Starting from CA 0x%" PRIx64 " lid %d port %d (leafport %d)",\r
+                                       node->nodeguid, port->lid, port->portnum, leafport);\r
+                       } else {        /* switch */\r
+\r
+                               /* if starting from a leaf port fix up port (up port) */\r
+                               if (dist == 1 && leafport)\r
+                                       node->upport = leafport;\r
+\r
+                               if (switch_mclookup(node, path, mlid, map) < 0) {\r
+                                       IBWARN("skipping bad Switch 0x%" PRIx64 "",\r
+                                               node->nodeguid);\r
+                                       continue;\r
+                               }\r
+                       }\r
+\r
+                       for (i = 1; i <= node->numports; i++) {\r
+                               if (!map[i] || i == node->upport)\r
+                                       continue;\r
+\r
+                               if (dist == 0 && leafport) {\r
+                                       if (from->drpath.cnt > 0)\r
+                                               path->drpath.cnt--;\r
+                               } else {\r
+                                       if (!(port = calloc(1, sizeof(Port))))\r
+                                               IBERROR("out of memory");\r
+\r
+                                       if (get_port(port, i, path) < 0) {\r
+                                               IBWARN("can't reach node %s port %d", portid2str(path), i);\r
+                                               return 0;\r
+                                       }\r
+\r
+                                       if (port->physstate != 5) {     /* LinkUP */\r
+                                               free(port);\r
+                                               continue;\r
+                                       }\r
+\r
+#if 0\r
+                                       link_port(port, node);\r
+#endif\r
+\r
+                                       if (extend_dpath(&path->drpath, i) < 0)\r
+                                               return 0;\r
+                               }\r
+\r
+                               if (!(remotenode = calloc(1, sizeof(Node))))\r
+                                       IBERROR("out of memory");\r
+\r
+                               if (!(remoteport = calloc(1, sizeof(Port))))\r
+                                       IBERROR("out of memory");\r
+\r
+                               if (get_node(remotenode, remoteport, path) < 0) {\r
+                                       IBWARN("NodeInfo on %s port %d failed, skipping port",\r
+                                               portid2str(path), i);\r
+                                       path->drpath.cnt--;     /* restore path */\r
+                                       free(remotenode);\r
+                                       free(remoteport);\r
+                                       continue;\r
+                               }\r
+\r
+                               remotenode->upnode = node;\r
+                               remotenode->upport = remoteport->portnum;\r
+                               remoteport->remoteport = port;\r
+\r
+                               if ((r = new_node(remotenode, remoteport, path, dist+1)) > 0)\r
+                                       return remotenode;\r
+\r
+                               if (r == 0)\r
+                                       dump_endnode(verbose, "new remote",\r
+                                               remotenode, remoteport);\r
+                               else if (remotenode->type == IB_NODE_SWITCH)\r
+                                       dump_endnode(2, "ERR: circle discovered at",\r
+                                               remotenode, remoteport);\r
+\r
+                               path->drpath.cnt--;     /* restore path */\r
+                       }\r
+               }\r
+       }\r
+\r
+       return 0;               /* not found */\r
+}\r
+\r
+static uint64_t\r
+find_target_portguid(ib_portid_t *to)\r
+{\r
+       Node tonode;\r
+       Port toport;\r
+\r
+       if (get_node(&tonode, &toport, to) < 0) {\r
+               IBWARN("can't find to port\n");\r
+               return -1;\r
+       }\r
+\r
+       return toport.portguid;\r
+}\r
+\r
+static void\r
+dump_mcpath(Node *node, int dumplevel)\r
+{\r
+       char *nodename = NULL;\r
+\r
+       if (node->upnode)\r
+               dump_mcpath(node->upnode, dumplevel);\r
+\r
+       nodename = remap_node_name(node_name_map, node->nodeguid, node->nodedesc);\r
+\r
+       if (!node->dist) {\r
+               printf("From %s 0x%" PRIx64 " port %d lid %u-%u \"%s\"\n",\r
+                       (node->type <= IB_NODE_MAX ? node_type_str[node->type] : "???"),\r
+                       node->nodeguid, node->ports->portnum, node->ports->lid,\r
+                       node->ports->lid + (1 << node->ports->lmc) - 1,\r
+                       nodename);\r
+               goto free_name;\r
+       }\r
+\r
+       if (node->dist) {\r
+               if (dumplevel == 1)\r
+                       printf("[%d] -> %s {0x%016" PRIx64 "}[%d]\n",\r
+                               node->ports->remoteport->portnum,\r
+                               (node->type <= IB_NODE_MAX ? node_type_str[node->type] : "???"),\r
+                               node->nodeguid, node->upport);\r
+               else\r
+                       printf("[%d] -> %s 0x%" PRIx64 "[%d] lid %u \"%s\"\n",\r
+                               node->ports->remoteport->portnum,\r
+                               (node->type <= IB_NODE_MAX ? node_type_str[node->type] : "???"),\r
+                               node->nodeguid, node->upport,\r
+                               node->ports->lid, nodename);\r
+       }\r
+\r
+       if (node->dist < 0)\r
+       /* target node */\r
+               printf("To %s 0x%" PRIx64 " port %d lid %u-%u \"%s\"\n",\r
+                       (node->type <= IB_NODE_MAX ? node_type_str[node->type] : "???"),\r
+                       node->nodeguid, node->ports->portnum, node->ports->lid,\r
+                       node->ports->lid + (1 << node->ports->lmc) - 1,\r
+                       nodename);\r
+\r
+free_name:\r
+       free(nodename);\r
+}\r
+\r
+static int resolve_lid(ib_portid_t  *portid, const void *srcport)\r
+{\r
+       uint8_t portinfo[64];\r
+       uint16_t lid;\r
+\r
+       if (!smp_query_via(portinfo, portid, IB_ATTR_PORT_INFO, 0, 0, srcport))\r
+               return -1;\r
+       mad_decode_field(portinfo, IB_PORT_LID_F, &lid);\r
+\r
+       ib_portid_set(portid, lid, 0, 0);\r
+\r
+       return 0;\r
+}\r
+\r
+static void\r
+usage(void)\r
+{\r
+       char *basename;\r
+\r
+       if (!(basename = strrchr(argv0, '/')))\r
+               basename = argv0;\r
+       else\r
+               basename++;\r
+\r
+       fprintf(stderr, "Usage: %s [-d(ebug) -v(erbose) -D(irect) -G(uids) -n(o_info) -C ca_name -P ca_port "\r
+                       "-s smlid -t(imeout) timeout_ms -m mlid --node-name-map node-name-map ] <src-addr> <dest-addr>\n",\r
+                       basename);\r
+       fprintf(stderr, "\n\tUnicast examples:\n");\r
+       fprintf(stderr, "\t\t%s 4 16\t\t\t# show path between lids 4 and 16\n", basename);\r
+       fprintf(stderr, "\t\t%s -n 4 16\t\t# same, but using simple output format\n", basename);\r
+       fprintf(stderr, "\t\t%s -G 0x8f1040396522d 0x002c9000100d051\t# use guid addresses\n", basename);\r
+\r
+       fprintf(stderr, "\n\tMulticast example:\n");\r
+       fprintf(stderr, "\t\t%s -m 0xc000 4 16\t# show multicast path of mlid 0xc000 between lids 4 and 16\n", basename);\r
+       exit(-1);\r
+}\r
+\r
+int\r
+main(int argc, char **argv)\r
+{\r
+       int mgmt_classes[3] = {IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS};\r
+       ib_portid_t my_portid = {0};\r
+       ib_portid_t src_portid = {0};\r
+       ib_portid_t dest_portid = {0};\r
+       ib_portid_t *sm_id = 0, sm_portid = {0};\r
+       int dumplevel = 2, dest_type = IB_DEST_LID, multicast = 0, mlid = 0;\r
+       Node *endnode;\r
+       int udebug = 0;\r
+       char *ca = 0;\r
+       int ca_port = 0;\r
+\r
+       static char const str_opts[] = "C:P:t:s:m:dvfDGnVhu";\r
+       static const struct option long_opts[] = {\r
+               { "C", 1, 0, 'C'},\r
+               { "P", 1, 0, 'P'},\r
+               { "debug", 0, 0, 'd'},\r
+               { "verbose", 0, 0, 'v'},\r
+               { "force", 0, 0, 'f'},\r
+               { "Direct", 0, 0, 'D'},\r
+               { "Guids", 0, 0, 'G'},\r
+               { "no_info", 0, 0, 'n'},\r
+               { "timeout", 1, 0, 't'},\r
+               { "s", 1, 0, 's'},\r
+               { "m", 1, 0, 'm'},\r
+               { "Version", 0, 0, 'V'},\r
+               { "help", 0, 0, 'h'},\r
+               { "usage", 0, 0, 'u'},\r
+               { "node-name-map", 1, 0, 1},\r
+               { }\r
+       };\r
+\r
+       argv0 = argv[0];\r
+\r
+       f = stdout;\r
+\r
+       while (1) {\r
+               int ch = getopt_long(argc, argv, str_opts, long_opts, NULL);\r
+               if ( ch == -1 )\r
+                       break;\r
+               switch(ch) {\r
+               case 1:\r
+                       node_name_map_file = strdup(optarg);\r
+                       break;\r
+               case 'C':\r
+                       ca = optarg;\r
+                       break;\r
+               case 'P':\r
+                       ca_port = strtoul(optarg, 0, 0);\r
+                       break;\r
+               case 'd':\r
+                       ibdebug++;\r
+                       madrpc_show_errors(1);\r
+                       umad_debug(udebug);\r
+                       udebug++;\r
+                       break;\r
+               case 'D':\r
+                       dest_type = IB_DEST_DRPATH;\r
+                       break;\r
+               case 'G':\r
+                       dest_type = IB_DEST_GUID;\r
+                       break;\r
+               case 'm':\r
+                       multicast++;\r
+                       mlid = strtoul(optarg, 0, 0);\r
+                       break;\r
+               case 'f':\r
+                       force++;\r
+                       break;\r
+               case 'n':\r
+                       dumplevel = 1;\r
+                       break;\r
+               case 's':\r
+                       if (ib_resolve_portid_str(&sm_portid, optarg, IB_DEST_LID, 0) < 0)\r
+                               IBERROR("can't resolve SM destination port %s", optarg);\r
+                       sm_id = &sm_portid;\r
+                       break;\r
+               case 't':\r
+                       timeout = strtoul(optarg, 0, 0);\r
+                       madrpc_set_timeout(timeout);\r
+                       break;\r
+               case 'v':\r
+                       madrpc_show_errors(1);\r
+                       verbose++;\r
+                       break;\r
+               case 'V':\r
+                       fprintf(stderr, "%s %s\n", argv0, get_build_version() );\r
+                       exit(-1);\r
+               default:\r
+                       usage();\r
+                       break;\r
+               }\r
+       }\r
+       argc -= optind;\r
+       argv += optind;\r
+\r
+       if (argc < 2)\r
+               usage();\r
+\r
+       madrpc_init(ca, ca_port, mgmt_classes, 3);\r
+       node_name_map = open_node_name_map(node_name_map_file);\r
+\r
+       if (ib_resolve_portid_str(&src_portid, argv[0], dest_type, sm_id) < 0)\r
+               IBERROR("can't resolve source port %s", argv[0]);\r
+\r
+       if (ib_resolve_portid_str(&dest_portid, argv[1], dest_type, sm_id) < 0)\r
+               IBERROR("can't resolve destination port %s", argv[1]);\r
+\r
+       if (dest_type == IB_DEST_DRPATH) {\r
+               if (resolve_lid(&src_portid, NULL) < 0)\r
+                       IBERROR("cannot resolve lid for port \'%s\'",\r
+                               portid2str(&src_portid));\r
+               if (resolve_lid(&dest_portid, NULL) < 0)\r
+                       IBERROR("cannot resolve lid for port \'%s\'",\r
+                               portid2str(&dest_portid));\r
+       }\r
+\r
+       if (dest_portid.lid == 0 || src_portid.lid == 0) {\r
+               IBWARN("bad src/dest lid");\r
+               usage();\r
+       }\r
+\r
+       if (dest_type != IB_DEST_DRPATH) {\r
+               /* first find a direct path to the src port */\r
+               if (find_route(&my_portid, &src_portid, 0) < 0)\r
+                       IBERROR("can't find a route to the src port");\r
+\r
+               src_portid = my_portid;\r
+       }\r
+\r
+       if (!multicast) {\r
+               if (find_route(&src_portid, &dest_portid, dumplevel) < 0)\r
+                       IBERROR("can't find a route from src to dest");\r
+               exit(0);\r
+       } else {\r
+               if (mlid < 0xc000)\r
+                       IBWARN("invalid MLID; must be 0xc000 or larger");\r
+       }\r
+\r
+       if (!(target_portguid = find_target_portguid(&dest_portid)))\r
+               IBERROR("can't reach target lid %d", dest_portid.lid);\r
+\r
+       if (!(endnode = find_mcpath(&src_portid, mlid)))\r
+               IBERROR("can't find a multicast route from src to dest");\r
+\r
+       /* dump multicast path */\r
+       dump_mcpath(endnode, dumplevel);\r
+\r
+       close_node_name_map(node_name_map);\r
+       exit(0);\r
+}\r
diff --git a/branches/winverbs/tools/infiniband_diags/src/mcm_rereg_test.c b/branches/winverbs/tools/infiniband_diags/src/mcm_rereg_test.c
new file mode 100644 (file)
index 0000000..1eb62ec
--- /dev/null
@@ -0,0 +1,489 @@
+/*\r
+ * Copyright (c) 2006 Voltaire, 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
+#include <stdio.h>\r
+#include <string.h>\r
+#include <errno.h>\r
+#include <inttypes.h>\r
+\r
+#include <infiniband/umad.h>\r
+#include <infiniband/mad.h>\r
+\r
+#define info(fmt, arg...) fprintf(stderr, "INFO: " fmt, ##arg )\r
+#define err(fmt, arg...) fprintf(stderr, "ERR: " fmt, ##arg )\r
+#ifdef NOISY_DEBUG\r
+#define dbg(fmt, arg...) fprintf(stderr, "DBG: " fmt, ##arg )\r
+#else\r
+#define dbg(fmt, arg...)\r
+#endif\r
+\r
+#define TMO 100\r
+\r
+/* Multicast Member Record Component Masks */\r
+#define IB_MCR_COMPMASK_MGID        (1ULL<<0)\r
+#define IB_MCR_COMPMASK_PORT_GID    (1ULL<<1)\r
+#define IB_MCR_COMPMASK_QKEY        (1ULL<<2)\r
+#define IB_MCR_COMPMASK_MLID        (1ULL<<3)\r
+#define IB_MCR_COMPMASK_MTU_SEL     (1ULL<<4)\r
+#define IB_MCR_COMPMASK_MTU         (1ULL<<5)\r
+#define IB_MCR_COMPMASK_TCLASS      (1ULL<<6)\r
+#define IB_MCR_COMPMASK_PKEY        (1ULL<<7)\r
+#define IB_MCR_COMPMASK_RATE_SEL    (1ULL<<8)\r
+#define IB_MCR_COMPMASK_RATE        (1ULL<<9)\r
+#define IB_MCR_COMPMASK_LIFE_SEL    (1ULL<<10)\r
+#define IB_MCR_COMPMASK_LIFE        (1ULL<<11)\r
+#define IB_MCR_COMPMASK_SL          (1ULL<<12)\r
+#define IB_MCR_COMPMASK_FLOW        (1ULL<<13)\r
+#define IB_MCR_COMPMASK_HOP         (1ULL<<14)\r
+#define IB_MCR_COMPMASK_SCOPE       (1ULL<<15)\r
+#define IB_MCR_COMPMASK_JOIN_STATE  (1ULL<<16)\r
+#define IB_MCR_COMPMASK_PROXY       (1ULL<<17)\r
+\r
+static ibmad_gid_t mgid_ipoib = {\r
+       0xff, 0x12, 0x40, 0x1b, 0xff, 0xff, 0x00, 0x00,\r
+       0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff\r
+};\r
+\r
+uint64_t build_mcm_rec(uint8_t *data, ibmad_gid_t mgid, ibmad_gid_t port_gid)\r
+{\r
+       memset(data, 0, IB_SA_DATA_SIZE);\r
+       mad_set_array(data, 0, IB_SA_MCM_MGID_F, mgid);\r
+       mad_set_array(data, 0, IB_SA_MCM_PORTGID_F, port_gid);\r
+       mad_set_field(data, 0, IB_SA_MCM_JOIN_STATE_F, 1);\r
+\r
+       return IB_MCR_COMPMASK_MGID|IB_MCR_COMPMASK_PORT_GID|\r
+               IB_MCR_COMPMASK_JOIN_STATE;\r
+}\r
+\r
+static void build_mcm_rec_umad(void *umad, ib_portid_t *dport, int method,\r
+                              uint64_t comp_mask, uint8_t *data)\r
+{\r
+       ib_rpc_t rpc;\r
+\r
+       memset(&rpc, 0, sizeof(rpc));\r
+       rpc.mgtclass = IB_SA_CLASS;\r
+       rpc.method = method;\r
+       rpc.attr.id = IB_SA_ATTR_MCRECORD;\r
+       rpc.attr.mod = 0; // ???\r
+       rpc.mask = comp_mask;\r
+       rpc.datasz = IB_SA_DATA_SIZE;\r
+       rpc.dataoffs = IB_SA_DATA_OFFS;\r
+\r
+       mad_build_pkt(umad, &rpc, dport, NULL, data);\r
+}\r
+\r
+static int rereg_send(int port, int agent, ib_portid_t *dport,\r
+                     uint8_t *umad, int len, int method, ibmad_gid_t port_gid)\r
+{\r
+       uint8_t data[IB_SA_DATA_SIZE];\r
+       uint64_t comp_mask;\r
+\r
+       comp_mask = build_mcm_rec(data, mgid_ipoib, port_gid);\r
+\r
+       build_mcm_rec_umad(umad, dport, method, comp_mask, data);\r
+       if(umad_send(port, agent, umad, len, TMO, 0) < 0) {\r
+               err("umad_send leave failed: %s\n", strerror(errno));\r
+               return -1;\r
+       }\r
+       dbg("umad_send %d: tid = 0x%016" PRIx64 "\n", method,\r
+           mad_get_field64(umad_get_mad(umad), 0, IB_MAD_TRID_F));\r
+\r
+       return 0;\r
+}\r
+\r
+static int rereg_port_gid(int port, int agent, ib_portid_t *dport,\r
+                         uint8_t *umad, int len, ibmad_gid_t port_gid)\r
+{\r
+       uint8_t data[IB_SA_DATA_SIZE];\r
+       uint64_t comp_mask;\r
+\r
+       comp_mask = build_mcm_rec(data, mgid_ipoib, port_gid);\r
+\r
+       build_mcm_rec_umad(umad, dport, IB_MAD_METHOD_DELETE,\r
+                          comp_mask, data);\r
+       if(umad_send(port, agent, umad, len, TMO, 0) < 0) {\r
+               err("umad_send leave failed: %s\n", strerror(errno));\r
+               return -1;\r
+       }\r
+       dbg("umad_send leave: tid = 0x%016" PRIx64 "\n",\r
+           mad_get_field64(umad_get_mad(umad), 0, IB_MAD_TRID_F));\r
+\r
+       build_mcm_rec_umad(umad, dport, IB_MAD_METHOD_SET,\r
+                          comp_mask, data);\r
+       if(umad_send(port, agent, umad, len, TMO, 0) < 0) {\r
+               err("umad_send join failed: %s\n", strerror(errno));\r
+               return -1;\r
+       }\r
+       dbg("umad_send join: tid = 0x%016" PRIx64 "\n",\r
+           mad_get_field64(umad_get_mad(umad), 0, IB_MAD_TRID_F));\r
+\r
+       return 0;\r
+}\r
+\r
+struct guid_trid {\r
+       ibmad_gid_t gid;\r
+       uint64_t guid;\r
+       uint64_t trid;\r
+};\r
+\r
+static int rereg_send_all(int port, int agent, ib_portid_t *dport,\r
+                         struct guid_trid *list, unsigned cnt)\r
+{\r
+       uint8_t *umad;\r
+       int len = umad_size() + 256;\r
+       int i, ret;\r
+\r
+       info("rereg_send_all... cnt = %u\n", cnt);\r
+\r
+       umad = calloc(1, len);\r
+       if (!umad) {\r
+               err("cannot alloc mem for umad: %s\n", strerror(errno));\r
+               return -1;\r
+       }\r
+\r
+       for (i = 0; i < cnt; i++) {\r
+               ret = rereg_port_gid(port, agent, dport, umad, len, list[i].gid);\r
+               if (ret < 0) {\r
+                       err("rereg_send_all: rereg_port_gid 0x%016" PRIx64\r
+                           " failed\n", list[i].guid);\r
+                       continue;\r
+               }\r
+               list[i].trid = mad_get_field64(umad_get_mad(umad), 0,\r
+                                              IB_MAD_TRID_F);\r
+       }\r
+\r
+       info("rereg_send_all: sent %u requests\n", cnt*2);\r
+\r
+       free(umad);\r
+\r
+       return 0;\r
+}\r
+\r
+#if 0\r
+static int rereg_mcm_rec_send(int port, int agent, ib_portid_t *dport, int cnt)\r
+{\r
+       ib_portid_t portid;\r
+       ibmad_gid_t port_gid;\r
+       uint8_t *umad;\r
+       int len, ret = 0;\r
+\r
+       ib_resolve_self(&portid, NULL, &port_gid);\r
+\r
+       len = umad_size() + 256;\r
+       umad = calloc(1, len);\r
+       if (!umad) {\r
+               err("cannot alloc mem for umad: %s\n", strerror(errno));\r
+               return -1;\r
+       }\r
+\r
+       while(cnt--) {\r
+               if (!rereg_port_gid(port, agent, dport, umad, len, port_gid))\r
+                       ret += 2;\r
+       }\r
+\r
+       free(umad);\r
+\r
+       return ret;\r
+}\r
+#endif\r
+\r
+static int rereg_recv(int port, int agent, ib_portid_t *dport,\r
+                     uint8_t *umad, int length, int tmo)\r
+{\r
+       int ret, retry = 0;\r
+       int len = length;\r
+\r
+       while((ret = umad_recv(port, umad, &len, tmo)) < 0 &&\r
+             errno == ETIMEDOUT) {\r
+               if (retry++ > 3)\r
+                       return 0;\r
+       }\r
+       if (ret < 0) {\r
+               err("umad_recv %d failed: %s\n", ret, strerror(errno));\r
+               return -1;\r
+       }\r
+       dbg("umad_recv (retries %d), tid = 0x%016" PRIx64 ": len = %d, status = %d\n",\r
+           retry,\r
+           mad_get_field64(umad_get_mad(umad), 0, IB_MAD_TRID_F),\r
+           len, umad_status(umad));\r
+\r
+       return 1;\r
+}\r
+\r
+static int rereg_recv_all(int port, int agent, ib_portid_t *dport,\r
+                         struct guid_trid *list, unsigned cnt)\r
+{\r
+       uint8_t *umad, *mad;\r
+       int len = umad_size() + 256;\r
+       uint64_t trid;\r
+       unsigned n, method, status;\r
+       int i;\r
+\r
+       info("rereg_recv_all...\n");\r
+\r
+       umad = calloc(1, len);\r
+       if (!umad) {\r
+               err("cannot alloc mem for umad: %s\n", strerror(errno));\r
+               return -1;\r
+       }\r
+\r
+       n = 0;\r
+       while (rereg_recv(port, agent, dport, umad, len, TMO) > 0) {\r
+               dbg("rereg_recv_all: done %d\n", n);\r
+               n++;\r
+               mad = umad_get_mad(umad);\r
+\r
+               method = mad_get_field(mad, 0, IB_MAD_METHOD_F);\r
+               status = mad_get_field(mad, 0, IB_MAD_STATUS_F);\r
+\r
+               if (status)\r
+                       dbg("MAD status %x, method %x\n", status, method);\r
+\r
+               if (status &&\r
+                   (method&0x7f) == (IB_MAD_METHOD_GET_RESPONSE&0x7f)) {\r
+                       trid = mad_get_field64(mad, 0, IB_MAD_TRID_F);\r
+                       for (i = 0; i < cnt; i++)\r
+                               if (trid == list[i].trid)\r
+                                       break;\r
+                       if (i == cnt) {\r
+                               err("cannot find trid 0x%016" PRIx64 "\n",\r
+                                   trid);\r
+                               continue;\r
+                       }\r
+                       info("guid 0x%016" PRIx64 ": method = %x status = %x. Resending\n",\r
+                            ntohll(list[i].guid), method, status);\r
+                       rereg_port_gid(port, agent, dport, umad, len,\r
+                                      list[i].gid);\r
+                       list[i].trid = mad_get_field64(umad_get_mad(umad), 0,\r
+                                                      IB_MAD_TRID_F);\r
+               }\r
+       }\r
+\r
+       info("rereg_recv_all: got %u responses\n", n);\r
+\r
+       free(umad);\r
+       return 0;\r
+}\r
+\r
+static int rereg_query_all(int port, int agent, ib_portid_t *dport,\r
+                          struct guid_trid *list, unsigned cnt)\r
+{\r
+       uint8_t *umad, *mad;\r
+       int len = umad_size() + 256;\r
+       unsigned method, status;\r
+       int i, ret;\r
+\r
+       info("rereg_query_all...\n");\r
+\r
+       umad = calloc(1, len);\r
+       if (!umad) {\r
+               err("cannot alloc mem for umad: %s\n", strerror(errno));\r
+               return -1;\r
+       }\r
+\r
+       for ( i = 0; i < cnt; i++ ) {\r
+               ret = rereg_send(port, agent, dport, umad, len,\r
+                                IB_MAD_METHOD_GET, list[i].gid);\r
+               if (ret < 0) {\r
+                       err("query_all: rereg_send failed.\n");\r
+                       continue;\r
+               }\r
+\r
+               ret = rereg_recv(port, agent, dport, umad, len, TMO);\r
+               if (ret < 0) {\r
+                       err("query_all: rereg_recv failed.\n");\r
+                       continue;\r
+               }\r
+\r
+               mad = umad_get_mad(umad);\r
+\r
+               method = mad_get_field(mad, 0, IB_MAD_METHOD_F);\r
+               status = mad_get_field(mad, 0, IB_MAD_STATUS_F);\r
+\r
+               if (status)\r
+                       info("guid 0x%016" PRIx64 ": status %x, method %x\n",\r
+                            ntohll(list[i].guid), status, method);\r
+       }\r
+\r
+       info("rereg_query_all: %u queried.\n", cnt);\r
+\r
+       free(umad);\r
+       return 0;\r
+}\r
+\r
+#if 0\r
+static int rereg_mcm_rec_recv(int port, int agent, int cnt)\r
+{\r
+       uint8_t *umad, *mad;\r
+       int len = umad_size() + 256;\r
+       int i;\r
+\r
+       umad = calloc(1, len);\r
+       if (!umad) {\r
+               err("cannot alloc mem for umad: %s\n", strerror(errno));\r
+               return -1;\r
+       }\r
+\r
+       for ( i = 0; i < cnt; i++ ) {\r
+               int retry;\r
+               retry = 0;\r
+               while (umad_recv(port, umad, &len, TMO) < 0 &&\r
+                      errno == ETIMEDOUT)\r
+                       if (retry++ > 3) {\r
+                               err("umad_recv %d failed: %s\n",\r
+                                   i, strerror(errno));\r
+                               free(umad);\r
+                               return -1;\r
+                       }\r
+               dbg("umad_recv %d (retries %d), tid = 0x%016" PRIx64 ": len = %d, status = %d\n",\r
+                   i, retry,\r
+                   mad_get_field64(umad_get_mad(umad), 0, IB_MAD_TRID_F),\r
+                   len, umad_status(umad));\r
+               mad = umad_get_mad(umad);\r
+       }\r
+\r
+       free(umad);\r
+       return 0;\r
+}\r
+#endif\r
+\r
+#define MAX_CLIENTS 50\r
+\r
+static int rereg_and_test_port(char *guid_file, int port, int agent, ib_portid_t *dport, int timeout)\r
+{\r
+       char line[256];\r
+       FILE *f;\r
+       ibmad_gid_t port_gid;\r
+       uint64_t prefix = htonll(0xfe80000000000000llu);\r
+       uint64_t guid = htonll(0x0002c90200223825llu);\r
+       struct guid_trid *list;\r
+       int i = 0;\r
+\r
+       list = calloc(MAX_CLIENTS, sizeof(*list));\r
+       if (!list) {\r
+               err("cannot alloc mem for guid/trid list: %s\n", strerror(errno));\r
+               return -1;\r
+       }\r
+\r
+       f = fopen(guid_file, "r");\r
+       if (!f) {\r
+               err("cannot open %s: %s\n", guid_file, strerror(errno));\r
+               return -1;\r
+       }\r
+\r
+       while (fgets(line, sizeof(line), f)) {\r
+               guid = strtoull(line, NULL, 0);\r
+               guid = htonll(guid);\r
+               memcpy(&port_gid[0], &prefix, 8);\r
+               memcpy(&port_gid[8], &guid, 8);\r
+\r
+               list[i].guid = guid;\r
+               memcpy(list[i].gid, port_gid, sizeof(list[i].gid));\r
+               list[i].trid = 0;\r
+               if (++i >= MAX_CLIENTS)\r
+                       break;\r
+       }\r
+       fclose(f);\r
+\r
+       rereg_send_all(port, agent, dport, list, i);\r
+       rereg_recv_all(port, agent, dport, list, i);\r
+\r
+       rereg_query_all(port, agent, dport, list, i);\r
+\r
+       free(list);\r
+       return 0;\r
+}\r
+\r
+int main(int argc, char **argv)\r
+{\r
+       char *guid_file = "port_guids.list";\r
+       int mgmt_classes[2] = {IB_SMI_CLASS, IB_SMI_DIRECT_CLASS};\r
+       ib_portid_t dport_id;\r
+       int port, agent;\r
+       uint8_t *umad, *mad;\r
+       int len;\r
+\r
+       if (argc > 1)\r
+               guid_file = argv[1];\r
+\r
+       madrpc_init(NULL, 0, mgmt_classes, 2);\r
+\r
+#if 1\r
+       ib_resolve_smlid(&dport_id, TMO);\r
+#else\r
+       memset(&dport_id, 0, sizeof(dport_id));\r
+       dport_id.lid = 1;\r
+#endif\r
+       dport_id.qp = 1;\r
+       if (!dport_id.qkey)\r
+               dport_id.qkey = IB_DEFAULT_QP1_QKEY;\r
+\r
+\r
+       len = umad_size() + 256;\r
+       umad = calloc(1, len);\r
+       if (!umad) {\r
+               err("cannot alloc mem for umad: %s\n", strerror(errno));\r
+               return -1;\r
+       }\r
+\r
+#if 1\r
+       port = madrpc_portid();\r
+#else\r
+       ret = umad_init();\r
+\r
+       port = umad_open_port(NULL, 0);\r
+       if (port < 0) {\r
+               err("umad_open_port failed: %s\n", strerror(errno));\r
+               return port;\r
+       }\r
+#endif\r
+\r
+       agent = umad_register(port, IB_SA_CLASS, 2, 0, NULL);\r
+\r
+#if 0\r
+       int cnt;\r
+       cnt = rereg_mcm_rec_send(port, agent, &dport_id, cnt);\r
+\r
+       rereg_recv_all(port, agent, &dport_id);\r
+#else\r
+       rereg_and_test_port(guid_file, port, agent, &dport_id, TMO);\r
+#endif\r
+       mad = umad_get_mad(umad);\r
+\r
+       free(umad);\r
+       umad_unregister(port, agent);\r
+       umad_close_port(port);\r
+       umad_done();\r
+\r
+       return 0;\r
+}\r
diff --git a/branches/winverbs/tools/infiniband_diags/src/perfquery.c b/branches/winverbs/tools/infiniband_diags/src/perfquery.c
new file mode 100644 (file)
index 0000000..641e03a
--- /dev/null
@@ -0,0 +1,518 @@
+/*\r
+ * Copyright (c) 2004-2008 Voltaire Inc.  All rights reserved.\r
+ * Copyright (c) 2007 Xsigo Systems 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
+#if defined(_WIN32) \r
+#include <windows.h>\r
+#include <winsock2.h>\r
+#include "..\..\..\..\etc\user\getopt.c"\r
+#else\r
+\r
+#if HAVE_CONFIG_H\r
+#  include <config.h>\r
+#endif /* HAVE_CONFIG_H */\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <unistd.h>\r
+#include <stdarg.h>\r
+#include <getopt.h>\r
+#include <netinet/in.h>\r
+#endif\r
+\r
+#include <infiniband/umad.h>\r
+#include <infiniband/mad.h>\r
+\r
+#include "ibdiag_common.h"\r
+\r
+struct perf_count {\r
+       uint32_t portselect;\r
+       uint32_t counterselect;\r
+       uint32_t symbolerrors;\r
+       uint32_t linkrecovers;\r
+       uint32_t linkdowned;\r
+       uint32_t rcverrors;\r
+       uint32_t rcvremotephyerrors;\r
+       uint32_t rcvswrelayerrors;\r
+       uint32_t xmtdiscards;\r
+       uint32_t xmtconstrainterrors;\r
+       uint32_t rcvconstrainterrors;\r
+       uint32_t linkintegrityerrors;\r
+       uint32_t excbufoverrunerrors;\r
+       uint32_t vl15dropped;\r
+       uint32_t xmtdata;\r
+       uint32_t rcvdata;\r
+       uint32_t xmtpkts;\r
+       uint32_t rcvpkts;\r
+};\r
+\r
+struct perf_count_ext {\r
+       uint32_t portselect;\r
+       uint32_t counterselect;\r
+       uint64_t portxmitdata;\r
+       uint64_t portrcvdata;\r
+       uint64_t portxmitpkts;\r
+       uint64_t portrcvpkts;\r
+       uint64_t portunicastxmitpkts;\r
+       uint64_t portunicastrcvpkts;\r
+       uint64_t portmulticastxmitpkits;\r
+       uint64_t portmulticastrcvpkts;\r
+};\r
+\r
+static uint8_t pc[1024];\r
+\r
+struct perf_count perf_count = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};\r
+struct perf_count_ext perf_count_ext = {0,0,0,0,0,0,0,0,0,0};\r
+\r
+char *argv0 = "perfquery";\r
+\r
+#define ALL_PORTS 0xFF\r
+\r
+static void\r
+usage(void)\r
+{\r
+       char *basename;\r
+\r
+       if (!(basename = strrchr(argv0, '/')))\r
+               basename = argv0;\r
+       else\r
+               basename++;\r
+\r
+       fprintf(stderr, "Usage: %s [-d(ebug) -G(uid) -a(ll_ports) -l(oop_ports) -r(eset_after_read) -C ca_name -P ca_port "\r
+                       "-R(eset_only) -t(imeout) timeout_ms -V(ersion) -h(elp)] [<lid|guid> [[port] [reset_mask]]]\n",\r
+                       basename);\r
+       fprintf(stderr, "\tExamples:\n");\r
+       fprintf(stderr, "\t\t%s\t\t# read local port's performance counters\n", basename);\r
+       fprintf(stderr, "\t\t%s 32 1\t\t# read performance counters from lid 32, port 1\n", basename);\r
+       fprintf(stderr, "\t\t%s -e 32 1\t# read extended performance counters from lid 32, port 1\n", basename);\r
+       fprintf(stderr, "\t\t%s -a 32\t\t# read performance counters from lid 32, all ports\n", basename);\r
+       fprintf(stderr, "\t\t%s -r 32 1\t# read performance counters and reset\n", basename);\r
+       fprintf(stderr, "\t\t%s -e -r 32 1\t# read extended performance counters and reset\n", basename);\r
+       fprintf(stderr, "\t\t%s -R 0x20 1\t# reset performance counters of port 1 only\n", basename);\r
+       fprintf(stderr, "\t\t%s -e -R 0x20 1\t# reset extended performance counters of port 1 only\n", basename);\r
+       fprintf(stderr, "\t\t%s -R -a 32\t# reset performance counters of all ports\n", basename);\r
+       fprintf(stderr, "\t\t%s -R 32 2 0x0fff\t# reset only error counters of port 2\n", basename);\r
+       fprintf(stderr, "\t\t%s -R 32 2 0xf000\t# reset only non-error counters of port 2\n", basename);\r
+       exit(-1);\r
+}\r
+\r
+/* Notes: IB semantics is to cap counters if count has exceeded limits.\r
+ * Therefore we must check for overflows and cap the counters if necessary.\r
+ *\r
+ * mad_decode_field and mad_encode_field assume 32 bit integers passed in\r
+ * for fields < 32 bits in length.\r
+ */\r
+\r
+static void aggregate_4bit(uint32_t *dest, uint32_t val)\r
+{\r
+       if ((((*dest) + val) < (*dest))\r
+           || ((*dest) + val) > 0xf)\r
+               (*dest) = 0xf;\r
+       else\r
+               (*dest) = (*dest) + val;\r
+}\r
+\r
+static void aggregate_8bit(uint32_t *dest, uint32_t val)\r
+{\r
+       if ((((*dest) + val) < (*dest))\r
+           || ((*dest) + val) > 0xff)\r
+               (*dest) = 0xff;\r
+       else\r
+               (*dest) = (*dest) + val;\r
+}\r
+\r
+static void aggregate_16bit(uint32_t *dest, uint32_t val)\r
+{\r
+       if ((((*dest) + val) < (*dest))\r
+           || ((*dest) + val) > 0xffff)\r
+               (*dest) = 0xffff;\r
+       else\r
+               (*dest) = (*dest) + val;\r
+}\r
+\r
+static void aggregate_32bit(uint32_t *dest, uint32_t val)\r
+{\r
+       if (((*dest) + val) < (*dest))\r
+               (*dest) = 0xffffffff;\r
+       else\r
+               (*dest) = (*dest) + val;\r
+}\r
+\r
+static void aggregate_64bit(uint64_t *dest, uint64_t val)\r
+{\r
+       if (((*dest) + val) < (*dest))\r
+               (*dest) = 0xffffffffffffffffULL;\r
+       else\r
+               (*dest) = (*dest) + val;\r
+}\r
+\r
+static void aggregate_perfcounters(void)\r
+{\r
+       uint32_t val;\r
+\r
+       mad_decode_field(pc, IB_PC_PORT_SELECT_F, &val);\r
+       perf_count.portselect = val;\r
+        mad_decode_field(pc, IB_PC_COUNTER_SELECT_F, &val);\r
+       perf_count.counterselect = val;\r
+        mad_decode_field(pc, IB_PC_ERR_SYM_F, &val);\r
+       aggregate_16bit(&perf_count.symbolerrors, val);\r
+        mad_decode_field(pc, IB_PC_LINK_RECOVERS_F, &val);\r
+       aggregate_8bit(&perf_count.linkrecovers, val);\r
+        mad_decode_field(pc, IB_PC_LINK_DOWNED_F, &val);\r
+       aggregate_8bit(&perf_count.linkdowned, val);\r
+        mad_decode_field(pc, IB_PC_ERR_RCV_F, &val);\r
+       aggregate_16bit(&perf_count.rcverrors, val);\r
+        mad_decode_field(pc, IB_PC_ERR_PHYSRCV_F, &val);\r
+       aggregate_16bit(&perf_count.rcvremotephyerrors, val);\r
+        mad_decode_field(pc, IB_PC_ERR_SWITCH_REL_F, &val);\r
+       aggregate_16bit(&perf_count.rcvswrelayerrors, val);\r
+        mad_decode_field(pc, IB_PC_XMT_DISCARDS_F, &val);\r
+       aggregate_16bit(&perf_count.xmtdiscards, val);\r
+        mad_decode_field(pc, IB_PC_ERR_XMTCONSTR_F, &val);\r
+       aggregate_8bit(&perf_count.xmtconstrainterrors, val);\r
+        mad_decode_field(pc, IB_PC_ERR_RCVCONSTR_F, &val);\r
+       aggregate_8bit(&perf_count.rcvconstrainterrors, val);\r
+        mad_decode_field(pc, IB_PC_ERR_LOCALINTEG_F, &val);\r
+       aggregate_4bit(&perf_count.linkintegrityerrors, val);\r
+        mad_decode_field(pc, IB_PC_ERR_EXCESS_OVR_F, &val);\r
+       aggregate_4bit(&perf_count.excbufoverrunerrors, val);\r
+        mad_decode_field(pc, IB_PC_VL15_DROPPED_F, &val);\r
+       aggregate_16bit(&perf_count.vl15dropped, val);\r
+        mad_decode_field(pc, IB_PC_XMT_BYTES_F, &val);\r
+       aggregate_32bit(&perf_count.xmtdata, val);\r
+        mad_decode_field(pc, IB_PC_RCV_BYTES_F, &val);\r
+       aggregate_32bit(&perf_count.rcvdata, val);\r
+        mad_decode_field(pc, IB_PC_XMT_PKTS_F, &val);\r
+       aggregate_32bit(&perf_count.xmtpkts, val);\r
+        mad_decode_field(pc, IB_PC_RCV_PKTS_F, &val);\r
+       aggregate_32bit(&perf_count.rcvpkts, val);\r
+}\r
+\r
+static void output_aggregate_perfcounters(ib_portid_t *portid)\r
+{\r
+       char buf[1024];\r
+       uint32_t val = ALL_PORTS;\r
+\r
+       /* set port_select to 255 to emulate AllPortSelect */\r
+       mad_encode_field(pc, IB_PC_PORT_SELECT_F, &val);\r
+       mad_encode_field(pc, IB_PC_COUNTER_SELECT_F, &perf_count.counterselect);\r
+       mad_encode_field(pc, IB_PC_ERR_SYM_F, &perf_count.symbolerrors);\r
+       mad_encode_field(pc, IB_PC_LINK_RECOVERS_F, &perf_count.linkrecovers);\r
+       mad_encode_field(pc, IB_PC_LINK_DOWNED_F, &perf_count.linkdowned);\r
+       mad_encode_field(pc, IB_PC_ERR_RCV_F, &perf_count.rcverrors);\r
+       mad_encode_field(pc, IB_PC_ERR_PHYSRCV_F, &perf_count.rcvremotephyerrors);\r
+       mad_encode_field(pc, IB_PC_ERR_SWITCH_REL_F, &perf_count.rcvswrelayerrors);\r
+       mad_encode_field(pc, IB_PC_XMT_DISCARDS_F, &perf_count.xmtdiscards);\r
+       mad_encode_field(pc, IB_PC_ERR_XMTCONSTR_F, &perf_count.xmtconstrainterrors);\r
+       mad_encode_field(pc, IB_PC_ERR_RCVCONSTR_F, &perf_count.rcvconstrainterrors);\r
+       mad_encode_field(pc, IB_PC_ERR_LOCALINTEG_F, &perf_count.linkintegrityerrors);\r
+       mad_encode_field(pc, IB_PC_ERR_EXCESS_OVR_F, &perf_count.excbufoverrunerrors);\r
+       mad_encode_field(pc, IB_PC_VL15_DROPPED_F, &perf_count.vl15dropped);\r
+       mad_encode_field(pc, IB_PC_XMT_BYTES_F, &perf_count.xmtdata);\r
+       mad_encode_field(pc, IB_PC_RCV_BYTES_F, &perf_count.rcvdata);\r
+       mad_encode_field(pc, IB_PC_XMT_PKTS_F, &perf_count.xmtpkts);\r
+       mad_encode_field(pc, IB_PC_RCV_PKTS_F, &perf_count.rcvpkts);\r
+\r
+       mad_dump_perfcounters(buf, sizeof buf, pc, sizeof pc);\r
+\r
+       printf("# Port counters: %s port %d\n%s", portid2str(portid), ALL_PORTS, buf);\r
+}\r
+\r
+static void aggregate_perfcounters_ext(void)\r
+{\r
+       uint32_t val;\r
+       uint64_t val64;\r
+\r
+       mad_decode_field(pc, IB_PC_EXT_PORT_SELECT_F, &val);\r
+       perf_count_ext.portselect = val;\r
+       mad_decode_field(pc, IB_PC_EXT_COUNTER_SELECT_F, &val);\r
+       perf_count_ext.counterselect = val;\r
+       mad_decode_field(pc, IB_PC_EXT_XMT_BYTES_F, &val64);\r
+       aggregate_64bit(&perf_count_ext.portxmitdata, val64);\r
+       mad_decode_field(pc, IB_PC_EXT_RCV_BYTES_F, &val64);\r
+       aggregate_64bit(&perf_count_ext.portrcvdata, val64);\r
+       mad_decode_field(pc, IB_PC_EXT_XMT_PKTS_F, &val64);\r
+       aggregate_64bit(&perf_count_ext.portxmitpkts, val64);\r
+       mad_decode_field(pc, IB_PC_EXT_RCV_PKTS_F, &val64);\r
+       aggregate_64bit(&perf_count_ext.portrcvpkts, val64);\r
+       mad_decode_field(pc, IB_PC_EXT_XMT_UPKTS_F, &val64);\r
+       aggregate_64bit(&perf_count_ext.portunicastxmitpkts, val64);\r
+       mad_decode_field(pc, IB_PC_EXT_RCV_UPKTS_F, &val64);\r
+       aggregate_64bit(&perf_count_ext.portunicastrcvpkts, val64);\r
+       mad_decode_field(pc, IB_PC_EXT_XMT_MPKTS_F, &val64);\r
+       aggregate_64bit(&perf_count_ext.portmulticastxmitpkits, val64);\r
+       mad_decode_field(pc, IB_PC_EXT_RCV_MPKTS_F, &val64);\r
+       aggregate_64bit(&perf_count_ext.portmulticastrcvpkts, val64);\r
+}\r
+\r
+static void output_aggregate_perfcounters_ext(ib_portid_t *portid)\r
+{\r
+       char buf[1024];\r
+       uint32_t val = ALL_PORTS;\r
+\r
+        /* set port_select to 255 to emulate AllPortSelect */\r
+        mad_encode_field(pc, IB_PC_EXT_PORT_SELECT_F, &val);\r
+       mad_encode_field(pc, IB_PC_EXT_COUNTER_SELECT_F, &perf_count_ext.counterselect);\r
+       mad_encode_field(pc, IB_PC_EXT_XMT_BYTES_F, &perf_count_ext.portxmitdata);\r
+       mad_encode_field(pc, IB_PC_EXT_RCV_BYTES_F, &perf_count_ext.portrcvdata);\r
+       mad_encode_field(pc, IB_PC_EXT_XMT_PKTS_F, &perf_count_ext.portxmitpkts);\r
+       mad_encode_field(pc, IB_PC_EXT_RCV_PKTS_F, &perf_count_ext.portrcvpkts);\r
+       mad_encode_field(pc, IB_PC_EXT_XMT_UPKTS_F, &perf_count_ext.portunicastxmitpkts);\r
+       mad_encode_field(pc, IB_PC_EXT_RCV_UPKTS_F, &perf_count_ext.portunicastrcvpkts);\r
+       mad_encode_field(pc, IB_PC_EXT_XMT_MPKTS_F, &perf_count_ext.portmulticastxmitpkits);\r
+       mad_encode_field(pc, IB_PC_EXT_RCV_MPKTS_F, &perf_count_ext.portmulticastrcvpkts);\r
+\r
+       mad_dump_perfcounters_ext(buf, sizeof buf, pc, sizeof pc);\r
+\r
+       printf("# Port counters: %s port %d\n%s", portid2str(portid), ALL_PORTS, buf);\r
+}\r
+\r
+static void dump_perfcounters(int extended, int timeout, uint16_t cap_mask, ib_portid_t *portid,\r
+                             int port, int aggregate)\r
+{\r
+       char buf[1024];\r
+\r
+       if (extended != 1) {\r
+               if (!port_performance_query(pc, portid, port, timeout))\r
+                       IBERROR("perfquery");\r
+               if (aggregate)\r
+                       aggregate_perfcounters();\r
+               else\r
+                       mad_dump_perfcounters(buf, sizeof buf, pc, sizeof pc);\r
+       } else {\r
+               if (!(cap_mask & 0x200)) /* 1.2 errata: bit 9 is extended counter support */\r
+                       IBWARN("PerfMgt ClassPortInfo 0x%x extended counters not indicated\n", cap_mask);\r
+\r
+               if (!port_performance_ext_query(pc, portid, port, timeout))\r
+                       IBERROR("perfextquery");\r
+               if (aggregate)\r
+                       aggregate_perfcounters_ext();\r
+               else\r
+                       mad_dump_perfcounters_ext(buf, sizeof buf, pc, sizeof pc);\r
+       }\r
+\r
+       if (!aggregate)\r
+               printf("# Port counters: %s port %d\n%s", portid2str(portid), port, buf);\r
+}\r
+\r
+static void reset_counters(int extended, int timeout, int mask, ib_portid_t *portid, int port)\r
+{\r
+       if (extended != 1) {\r
+               if (!port_performance_reset(pc, portid, port, mask, timeout))\r
+                       IBERROR("perf reset");\r
+       } else {\r
+               if (!port_performance_ext_reset(pc, portid, port, mask, timeout))\r
+                       IBERROR("perf ext reset");\r
+       }\r
+}\r
+\r
+int __cdecl\r
+main(int argc, char **argv)\r
+{\r
+       int mgmt_classes[4] = {IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS, IB_PERFORMANCE_CLASS};\r
+       ib_portid_t *sm_id = 0, sm_portid = {0};\r
+       ib_portid_t portid = {0};\r
+       extern int ibdebug;\r
+       int dest_type = IB_DEST_LID;\r
+       int timeout = 0;        /* use default */\r
+       int mask = 0xffff, all_ports = 0;\r
+       int reset = 0, reset_only = 0;\r
+       int port = 0;\r
+       int udebug = 0;\r
+       char *ca = 0;\r
+       int ca_port = 0;\r
+       int extended = 0;\r
+       uint16_t cap_mask;\r
+       int all_ports_loop = 0;\r
+       int loop_ports = 0;\r
+       int node_type, num_ports = 0;\r
+       uint8_t data[IB_SMP_DATA_SIZE];\r
+       int start_port = 1;\r
+       int enhancedport0;\r
+       int i;\r
+\r
+       static char str_opts[] = "C:P:s:t:dGealrRVhu";\r
+       static struct option long_opts[] = {\r
+               { "C", 1, 0, 'C'},\r
+               { "P", 1, 0, 'P'},\r
+               { "debug", 0, 0, 'd'},\r
+               { "Guid", 0, 0, 'G'},\r
+               { "extended", 0, 0, 'e'},\r
+               { "all_ports", 0, 0, 'a'},\r
+               { "loop_ports", 0, 0, 'l'},\r
+               { "reset_after_read", 0, 0, 'r'},\r
+               { "Reset_only", 0, 0, 'R'},\r
+               { "sm_portid", 1, 0, 's'},\r
+               { "timeout", 1, 0, 't'},\r
+               { "Version", 0, 0, 'V'},\r
+               { "help", 0, 0, 'h'},\r
+               { "usage", 0, 0, 'u'},\r
+               { 0 }\r
+       };\r
+\r
+       argv0 = argv[0];\r
+\r
+       while (1) {\r
+               int ch = getopt_long(argc, argv, str_opts, long_opts, NULL);\r
+               if ( ch == -1 )\r
+                       break;\r
+               switch(ch) {\r
+               case 'C':\r
+                       ca = optarg;\r
+                       break;\r
+               case 'P':\r
+                       ca_port = strtoul(optarg, 0, 0);\r
+                       break;\r
+               case 'e':\r
+                       extended = 1;\r
+                       break;\r
+               case 'a':\r
+                       all_ports++;\r
+                       port = ALL_PORTS;\r
+                       break;\r
+               case 'l':\r
+                       loop_ports++;\r
+                       break;\r
+               case 'd':\r
+                       ibdebug++;\r
+                       madrpc_show_errors(1);\r
+                       umad_debug(udebug);\r
+                       udebug++;\r
+                       break;\r
+               case 'G':\r
+                       dest_type = IB_DEST_GUID;\r
+                       break;\r
+               case 's':\r
+                       if (ib_resolve_portid_str(&sm_portid, optarg, IB_DEST_LID, 0) < 0)\r
+                               IBERROR("can't resolve SM destination port %s", optarg);\r
+                       sm_id = &sm_portid;\r
+                       break;\r
+               case 'r':\r
+                       reset++;\r
+                       break;\r
+               case 'R':\r
+                       reset_only++;\r
+                       break;\r
+               case 't':\r
+                       timeout = strtoul(optarg, 0, 0);\r
+                       madrpc_set_timeout(timeout);\r
+                       break;\r
+               case 'V':\r
+                       fprintf(stderr, "%s %s\n", argv0, get_build_version() );\r
+                       exit(-1);\r
+               default:\r
+                       usage();\r
+                       break;\r
+               }\r
+       }\r
+       argc -= optind;\r
+       argv += optind;\r
+\r
+       if (argc > 1)\r
+               port = strtoul(argv[1], 0, 0);\r
+       if (argc > 2)\r
+               mask = strtoul(argv[2], 0, 0);\r
+\r
+       madrpc_init(ca, ca_port, mgmt_classes, 4);\r
+\r
+       if (argc) {\r
+               if (ib_resolve_portid_str(&portid, argv[0], dest_type, sm_id) < 0)\r
+                       IBERROR("can't resolve destination port %s", argv[0]);\r
+       } else {\r
+               if (ib_resolve_self(&portid, &port, 0) < 0)\r
+                       IBERROR("can't resolve self port %s", argv[0]);\r
+       }\r
+\r
+       /* PerfMgt ClassPortInfo is a required attribute */\r
+       if (!perf_classportinfo_query(pc, &portid, port, timeout))\r
+               IBERROR("classportinfo query");\r
+       /* ClassPortInfo should be supported as part of libibmad */\r
+       memcpy(&cap_mask, pc+2, sizeof(cap_mask));      /* CapabilityMask */\r
+       cap_mask = ntohs(cap_mask);\r
+       if (!(cap_mask & 0x100)) { /* bit 8 is AllPortSelect */\r
+               if (!all_ports && port == ALL_PORTS)\r
+                       IBERROR("AllPortSelect not supported");\r
+               if (all_ports)\r
+                       all_ports_loop = 1;\r
+       }\r
+\r
+       if (all_ports_loop || (loop_ports && (all_ports || port == ALL_PORTS))) {\r
+               if (smp_query(data, &portid, IB_ATTR_NODE_INFO, 0, 0) < 0)\r
+                       IBERROR("smp query nodeinfo failed");\r
+               node_type = mad_get_field(data, 0, IB_NODE_TYPE_F);\r
+               mad_decode_field(data, IB_NODE_NPORTS_F, &num_ports);\r
+               if (!num_ports)\r
+                       IBERROR("smp query nodeinfo: num ports invalid");\r
+\r
+               if (node_type == IB_NODE_SWITCH) {\r
+                       if (smp_query(data, &portid, IB_ATTR_SWITCH_INFO, 0, 0) < 0)\r
+                               IBERROR("smp query nodeinfo failed");\r
+                       enhancedport0 = mad_get_field(data, 0, IB_SW_ENHANCED_PORT0_F);\r
+                       if (enhancedport0)\r
+                               start_port = 0;\r
+               }\r
+               if (all_ports_loop && !loop_ports)\r
+                       IBWARN("Emulating AllPortSelect by iterating through all ports");\r
+       }\r
+\r
+       if (reset_only)\r
+               goto do_reset;\r
+\r
+       if (all_ports_loop || (loop_ports && (all_ports || port == ALL_PORTS))) {\r
+               for (i = start_port; i <= num_ports; i++)\r
+                       dump_perfcounters(extended, timeout, cap_mask, &portid, i,\r
+                                         (all_ports_loop && !loop_ports));\r
+               if (all_ports_loop && !loop_ports) {\r
+                       if (extended != 1)\r
+                               output_aggregate_perfcounters(&portid);\r
+                       else\r
+                               output_aggregate_perfcounters_ext(&portid);\r
+               }\r
+       }\r
+       else\r
+               dump_perfcounters(extended, timeout, cap_mask, &portid, port, 0);\r
+\r
+       if (!reset)\r
+               exit(0);\r
+\r
+do_reset:\r
+\r
+       if (all_ports_loop || (loop_ports && (all_ports || port == ALL_PORTS))) {\r
+               for (i = start_port; i <= num_ports; i++)\r
+                       reset_counters(extended, timeout, mask, &portid, i);\r
+       }\r
+       else\r
+               reset_counters(extended, timeout, mask, &portid, port);\r
+\r
+       exit(0);\r
+}\r
diff --git a/branches/winverbs/tools/infiniband_diags/src/perfquery/SOURCES b/branches/winverbs/tools/infiniband_diags/src/perfquery/SOURCES
new file mode 100644 (file)
index 0000000..30ebc33
--- /dev/null
@@ -0,0 +1,32 @@
+TARGETNAME = perfquery\r
+TARGETPATH = ..\..\..\..\bin\user\obj$(BUILD_ALT_DIR)\r
+TARGETTYPE = PROGRAM\r
+\r
+UMTYPE = console\r
+UMENTRY = main\r
+\r
+USE_MSVCRT = 1\r
+USE_STL = 1\r
+USE_NATIVE_EH = 1\r
+USE_IOSTREAM = 1\r
+\r
+SOURCES = ..\perfquery.c ..\ibdiag_common.c\r
+       \r
+INCLUDES = ..;..\..\include;..\..\..\..\ulp\libibmad\include;..\..\..\..\ulp\libibumad\include;..\..\..\..\inc;..\..\..\..\inc\user;\r
+\r
+TARGETLIBS =   \\r
+       $(SDK_LIB_PATH)\kernel32.lib    \\r
+       $(SDK_LIB_PATH)\advapi32.lib    \\r
+       $(SDK_LIB_PATH)\user32.lib      \\r
+       $(SDK_LIB_PATH)\ole32.lib       \\r
+       $(SDK_LIB_PATH)\ws2_32.lib      \\r
+!if $(FREEBUILD)\r
+       $(TARGETPATH)\*\complib.lib     \\r
+       $(TARGETPATH)\*\libibmad.lib    \\r
+       $(TARGETPATH)\*\libibumad.lib   \r
+!else\r
+       $(TARGETPATH)\*\complibd.lib    \\r
+       $(TARGETPATH)\*\libibmadd.lib   \\r
+       $(TARGETPATH)\*\libibumadd.lib  \r
+!endif\r
+\r
diff --git a/branches/winverbs/tools/infiniband_diags/src/saquery.c b/branches/winverbs/tools/infiniband_diags/src/saquery.c
new file mode 100644 (file)
index 0000000..fa895bb
--- /dev/null
@@ -0,0 +1,1830 @@
+/*\r
+ * Copyright (c) 2006,2007 The Regents of the University of California.\r
+ * Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.\r
+ * Copyright (c) 2002-2005 Mellanox Technologies LTD. All rights reserved.\r
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.\r
+ *\r
+ * Produced at Lawrence Livermore National Laboratory.\r
+ * Written by Ira Weiny <weiny2@llnl.gov>.\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
+#if defined(_WIN32) || defined(_WIN64)\r
+\r
+#include <windows.h>\r
+#include <winsock2.h>\r
+#include <ws2tcpip.h> \r
+#include <complib/cl_debug.h>\r
+#include <opensm/osm_log.h>\r
+#include <vendor/osm_vendor_api.h>\r
+#include <vendor/osm_vendor_sa_api.h>\r
+#include <opensm/osm_mad_pool.h>\r
+\r
+#else\r
+\r
+#include <unistd.h>\r
+#include <stdio.h>\r
+#include <sys/types.h>\r
+#include <sys/socket.h>\r
+#include <arpa/inet.h>\r
+#include <assert.h>\r
+#include <ctype.h>\r
+#include <string.h>\r
+\r
+#define _GNU_SOURCE\r
+#include <getopt.h>\r
+#include <infiniband/opensm/osm_log.h>\r
+#include <infiniband/vendor/osm_vendor_api.h>\r
+#include <infiniband/vendor/osm_vendor_sa_api.h>\r
+#include <infiniband/opensm/osm_mad_pool.h>\r
+#include <infiniband/complib/cl_debug.h>\r
+#include <infiniband/complib/cl_nodenamemap.h>\r
+\r
+#endif\r
+\r
+#include "ibdiag_common.h"\r
+\r
+struct query_cmd {\r
+       const char *name, *alias;\r
+       ib_net16_t query_type;\r
+       const char *usage;\r
+       int (*handler)(const struct query_cmd *q, osm_bind_handle_t bind_handle,\r
+                      int argc, char *argv[]);\r
+};\r
+\r
+char *argv0 = "saquery";\r
+\r
+static char *node_name_map_file = NULL;\r
+static nn_map_t *node_name_map = NULL;\r
+static ib_net64_t smkey = OSM_DEFAULT_SA_KEY;\r
+\r
+/**\r
+ * Declare some globals because I don't want this to be too complex.\r
+ */\r
+#define MAX_PORTS (8)\r
+#define DEFAULT_SA_TIMEOUT_MS (1000)\r
+osmv_query_res_t   result;\r
+osm_log_t          log_osm;\r
+osm_mad_pool_t     mad_pool;\r
+osm_vendor_t      *vendor = NULL;\r
+int                osm_debug = 0;\r
+uint32_t           sa_timeout_ms = DEFAULT_SA_TIMEOUT_MS;\r
+char             *sa_hca_name = NULL;\r
+uint32_t           sa_port_num = 0;\r
+\r
+enum {\r
+       ALL,\r
+       LID_ONLY,\r
+       UNIQUE_LID_ONLY,\r
+       GUID_ONLY,\r
+       ALL_DESC,\r
+       NAME_OF_LID,\r
+       NAME_OF_GUID,\r
+} node_print_desc = ALL;\r
+\r
+char              *requested_name = NULL;\r
+ib_net16_t         requested_lid = 0;\r
+int                requested_lid_flag = 0;\r
+ib_net64_t         requested_guid = 0;\r
+int                requested_guid_flag = 0;\r
+\r
+/**\r
+ * Call back for the various record requests.\r
+ */\r
+static void\r
+query_res_cb(osmv_query_res_t *res)\r
+{\r
+       result = *res;\r
+}\r
+\r
+static void\r
+print_node_desc(ib_node_record_t *node_record)\r
+{\r
+       ib_node_info_t *p_ni = &(node_record->node_info);\r
+       ib_node_desc_t *p_nd = &(node_record->node_desc);\r
+\r
+       if (p_ni->node_type == IB_NODE_TYPE_CA)\r
+       {\r
+               printf("%6d  \"%s\"\n",\r
+                      cl_ntoh16(node_record->lid),\r
+                      clean_nodedesc((char *)p_nd->description));\r
+       }\r
+}\r
+\r
+static void\r
+print_node_record(ib_node_record_t *node_record)\r
+{\r
+       ib_node_info_t *p_ni = NULL;\r
+       ib_node_desc_t *p_nd = NULL;\r
+       char *name;\r
+\r
+       p_ni = &(node_record->node_info);\r
+        p_nd = &(node_record->node_desc);\r
+\r
+       switch (node_print_desc) {\r
+       case LID_ONLY:\r
+       case UNIQUE_LID_ONLY:\r
+               printf("%d\n", cl_ntoh16(node_record->lid));\r
+               return;\r
+       case GUID_ONLY:\r
+               printf("0x%016" PRIx64 "\n", cl_ntoh64(p_ni->port_guid));\r
+               return;\r
+       case NAME_OF_LID:\r
+       case NAME_OF_GUID:\r
+               name = remap_node_name(node_name_map,\r
+                                         cl_ntoh64(p_ni->node_guid),\r
+                                         (char *)p_nd->description);\r
+               printf("%s\n", name);\r
+               free(name);\r
+               return;\r
+       case ALL:\r
+       default:\r
+               break;\r
+        }\r
+\r
+       printf("NodeRecord dump:\n"\r
+              "\t\tlid.....................0x%X\n"\r
+              "\t\treserved................0x%X\n"\r
+              "\t\tbase_version............0x%X\n"\r
+              "\t\tclass_version...........0x%X\n"\r
+              "\t\tnode_type...............%s\n"\r
+              "\t\tnum_ports...............0x%X\n"\r
+              "\t\tsys_guid................0x%016" PRIx64 "\n"\r
+              "\t\tnode_guid...............0x%016" PRIx64 "\n"\r
+              "\t\tport_guid...............0x%016" PRIx64 "\n"\r
+              "\t\tpartition_cap...........0x%X\n"\r
+              "\t\tdevice_id...............0x%X\n"\r
+              "\t\trevision................0x%X\n"\r
+              "\t\tport_num................0x%X\n"\r
+              "\t\tvendor_id...............0x%X\n"\r
+              "\t\tNodeDescription.........%s\n"\r
+              "",\r
+              cl_ntoh16(node_record->lid),\r
+              cl_ntoh16(node_record->resv),\r
+              p_ni->base_version,\r
+              p_ni->class_version,\r
+              ib_get_node_type_str( p_ni->node_type ),\r
+              p_ni->num_ports,\r
+              cl_ntoh64( p_ni->sys_guid ),\r
+              cl_ntoh64( p_ni->node_guid ),\r
+              cl_ntoh64( p_ni->port_guid ),\r
+              cl_ntoh16( p_ni->partition_cap ),\r
+              cl_ntoh16( p_ni->device_id ),\r
+              cl_ntoh32( p_ni->revision ),\r
+              ib_node_info_get_local_port_num( p_ni ),\r
+              cl_ntoh32( ib_node_info_get_vendor_id( p_ni )),\r
+              clean_nodedesc((char *)node_record->node_desc.description)\r
+              );\r
+}\r
+\r
+static void dump_path_record(void *data)\r
+{\r
+       char gid_str[INET6_ADDRSTRLEN];\r
+       char gid_str2[INET6_ADDRSTRLEN];\r
+       ib_path_rec_t *p_pr = data;\r
+       printf("PathRecord dump:\n"\r
+              "\t\tservice_id..............0x%016" PRIx64 "\n"\r
+              "\t\tdgid....................%s\n"\r
+              "\t\tsgid....................%s\n"\r
+              "\t\tdlid....................0x%X\n"\r
+              "\t\tslid....................0x%X\n"\r
+              "\t\thop_flow_raw............0x%X\n"\r
+              "\t\ttclass..................0x%X\n"\r
+              "\t\tnum_path_revers.........0x%X\n"\r
+              "\t\tpkey....................0x%X\n"\r
+              "\t\tqos_class...............0x%X\n"\r
+              "\t\tsl......................0x%X\n"\r
+              "\t\tmtu.....................0x%X\n"\r
+              "\t\trate....................0x%X\n"\r
+              "\t\tpkt_life................0x%X\n"\r
+              "\t\tpreference..............0x%X\n"\r
+              "\t\tresv2...................0x%X\n"\r
+              "\t\tresv3...................0x%X\n"\r
+              "",\r
+              cl_ntoh64( p_pr->service_id ),\r
+              inet_ntop(AF_INET6, p_pr->dgid.raw, gid_str, sizeof gid_str),\r
+              inet_ntop(AF_INET6, p_pr->sgid.raw, gid_str2, sizeof gid_str2),\r
+              cl_ntoh16( p_pr->dlid ),\r
+              cl_ntoh16( p_pr->slid ),\r
+              cl_ntoh32( p_pr->hop_flow_raw ),\r
+              p_pr->tclass,\r
+              p_pr->num_path,\r
+              cl_ntoh16( p_pr->pkey ),\r
+              ib_path_rec_qos_class( p_pr ),\r
+              ib_path_rec_sl( p_pr ),\r
+              p_pr->mtu,\r
+              p_pr->rate,\r
+              p_pr->pkt_life,\r
+              p_pr->preference,\r
+              *(uint32_t*)&p_pr->resv2,\r
+              *((uint16_t*)&p_pr->resv2 + 2)\r
+              );\r
+}\r
+\r
+static void dump_class_port_info(void *data)\r
+{\r
+       char   gid_str[INET6_ADDRSTRLEN];\r
+       char   gid_str2[INET6_ADDRSTRLEN];\r
+       ib_class_port_info_t *class_port_info = data;\r
+\r
+       printf("SA ClassPortInfo:\n"\r
+              "\t\tBase version.............%d\n"\r
+              "\t\tClass version............%d\n"\r
+              "\t\tCapability mask..........0x%04X\n"\r
+              "\t\tCapability mask 2........0x%08X\n"\r
+              "\t\tResponse time value......0x%02X\n"\r
+              "\t\tRedirect GID.............%s\n"\r
+              "\t\tRedirect TC/SL/FL........0x%08X\n"\r
+              "\t\tRedirect LID.............0x%04X\n"\r
+              "\t\tRedirect PKey............0x%04X\n"\r
+              "\t\tRedirect QP..............0x%08X\n"\r
+              "\t\tRedirect QKey............0x%08X\n"\r
+              "\t\tTrap GID.................%s\n"\r
+              "\t\tTrap TC/SL/FL............0x%08X\n"\r
+              "\t\tTrap LID.................0x%04X\n"\r
+              "\t\tTrap PKey................0x%04X\n"\r
+              "\t\tTrap HL/QP...............0x%08X\n"\r
+              "\t\tTrap QKey................0x%08X\n"\r
+              "",\r
+              class_port_info->base_ver,\r
+              class_port_info->class_ver,\r
+              cl_ntoh16(class_port_info->cap_mask),\r
+              ib_class_cap_mask2(class_port_info),\r
+              ib_class_resp_time_val(class_port_info),\r
+              inet_ntop(AF_INET6, &(class_port_info->redir_gid), gid_str,\r
+                       sizeof gid_str),\r
+              cl_ntoh32(class_port_info->redir_tc_sl_fl),\r
+              cl_ntoh16(class_port_info->redir_lid),\r
+              cl_ntoh16(class_port_info->redir_pkey),\r
+              cl_ntoh32(class_port_info->redir_qp),\r
+              cl_ntoh32(class_port_info->redir_qkey),\r
+              inet_ntop(AF_INET6, &(class_port_info->trap_gid), gid_str2,\r
+                       sizeof gid_str2),\r
+              cl_ntoh32(class_port_info->trap_tc_sl_fl),\r
+              cl_ntoh16(class_port_info->trap_lid),\r
+              cl_ntoh16(class_port_info->trap_pkey),\r
+              cl_ntoh32(class_port_info->trap_hop_qp),\r
+              cl_ntoh32(class_port_info->trap_qkey)\r
+             );\r
+}\r
+\r
+static void dump_portinfo_record(void *data)\r
+{\r
+       ib_portinfo_record_t *p_pir = data;\r
+       const ib_port_info_t * const p_pi = &p_pir->port_info;\r
+\r
+        printf("PortInfoRecord dump:\n"\r
+              "\t\tEndPortLid..............0x%X\n"\r
+              "\t\tPortNum.................0x%X\n"\r
+              "\t\tbase_lid................0x%X\n"\r
+              "\t\tmaster_sm_base_lid......0x%X\n"\r
+              "\t\tcapability_mask.........0x%X\n"\r
+              "",\r
+              cl_ntoh16(p_pir->lid),\r
+              p_pir->port_num,\r
+              cl_ntoh16( p_pi->base_lid ),\r
+              cl_ntoh16( p_pi->master_sm_base_lid ),\r
+              cl_ntoh32( p_pi->capability_mask )\r
+               );\r
+}\r
+\r
+static void dump_multicast_group_record(void *data)\r
+{\r
+       char   gid_str[INET6_ADDRSTRLEN];\r
+       ib_member_rec_t *p_mcmr = data;\r
+       uint8_t sl;\r
+       ib_member_get_sl_flow_hop(p_mcmr->sl_flow_hop, &sl, NULL, NULL);\r
+       printf("MCMemberRecord group dump:\n"\r
+              "\t\tMGID....................%s\n"\r
+              "\t\tMlid....................0x%X\n"\r
+              "\t\tMtu.....................0x%X\n"\r
+              "\t\tpkey....................0x%X\n"\r
+              "\t\tRate....................0x%X\n"\r
+              "\t\tSL......................0x%X\n"\r
+              "",\r
+              inet_ntop(AF_INET6, p_mcmr->mgid.raw, gid_str, sizeof gid_str),\r
+              cl_ntoh16( p_mcmr->mlid ),\r
+              p_mcmr->mtu,\r
+              cl_ntoh16( p_mcmr->pkey ),\r
+              p_mcmr->rate,\r
+              sl\r
+              );\r
+}\r
+\r
+static void dump_multicast_member_record(void *data)\r
+{\r
+       char   gid_str[INET6_ADDRSTRLEN];\r
+       char   gid_str2[INET6_ADDRSTRLEN];\r
+       ib_member_rec_t *p_mcmr = data;\r
+       uint16_t mlid = cl_ntoh16( p_mcmr->mlid );\r
+       int      i = 0;\r
+       char *node_name = "<unknown>";\r
+\r
+       /* go through the node records searching for a port guid which matches\r
+        * this port gid interface id.\r
+        * This gives us a node name to print, if available.\r
+        */\r
+       for (i = 0; i < result.result_cnt; i++) {\r
+               ib_node_record_t *nr = osmv_get_query_node_rec(result.p_result_madw, i);\r
+               if (nr->node_info.port_guid == p_mcmr->port_gid.unicast.interface_id) {\r
+                       node_name = clean_nodedesc((char *)nr->node_desc.description);\r
+                       break;\r
+               }\r
+       }\r
+\r
+       if (requested_name) {\r
+               if (strtol(requested_name, NULL, 0) == mlid) {\r
+                       printf("\t\tPortGid.................%s (%s)\n",\r
+                               inet_ntop(AF_INET6, p_mcmr->port_gid.raw,\r
+                                       gid_str, sizeof gid_str),\r
+                              node_name\r
+                             );\r
+               }\r
+       } else {\r
+               printf("MCMemberRecord member dump:\n"\r
+                      "\t\tMGID....................%s\n"\r
+                      "\t\tMlid....................0x%X\n"\r
+                      "\t\tPortGid.................%s\n"\r
+                      "\t\tScopeState..............0x%X\n"\r
+                      "\t\tProxyJoin...............0x%X\n"\r
+                      "\t\tNodeDescription.........%s\n"\r
+                      "",\r
+                      inet_ntop(AF_INET6, p_mcmr->mgid.raw, gid_str,\r
+                               sizeof gid_str),\r
+                      cl_ntoh16( p_mcmr->mlid ),\r
+                      inet_ntop(AF_INET6, p_mcmr->port_gid.raw,\r
+                               gid_str2, sizeof gid_str2),\r
+                      p_mcmr->scope_state,\r
+                      p_mcmr->proxy_join,\r
+                      node_name\r
+                     );\r
+       }\r
+}\r
+\r
+static void dump_service_record(void *data)\r
+{\r
+       char   gid_str[INET6_ADDRSTRLEN];\r
+       char buf_service_key[35];\r
+       char buf_service_name[65];\r
+       ib_service_record_t *p_sr = data;\r
+\r
+       sprintf(buf_service_key,\r
+               "0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",\r
+               p_sr->service_key[0],\r
+               p_sr->service_key[1],\r
+               p_sr->service_key[2],\r
+               p_sr->service_key[3],\r
+               p_sr->service_key[4],\r
+               p_sr->service_key[5],\r
+               p_sr->service_key[6],\r
+               p_sr->service_key[7],\r
+               p_sr->service_key[8],\r
+               p_sr->service_key[9],\r
+               p_sr->service_key[10],\r
+               p_sr->service_key[11],\r
+               p_sr->service_key[12],\r
+               p_sr->service_key[13],\r
+               p_sr->service_key[14],\r
+               p_sr->service_key[15]);\r
+       strncpy(buf_service_name, (char *)p_sr->service_name, 64);\r
+       buf_service_name[64] = '\0';\r
+\r
+       printf("ServiceRecord dump:\n"\r
+              "\t\tServiceID...............0x%016" PRIx64 "\n"\r
+              "\t\tServiceGID..............%s\n"\r
+              "\t\tServiceP_Key............0x%X\n"\r
+              "\t\tServiceLease............0x%X\n"\r
+              "\t\tServiceKey..............%s\n"\r
+              "\t\tServiceName.............%s\n"\r
+              "\t\tServiceData8.1..........0x%X\n"\r
+              "\t\tServiceData8.2..........0x%X\n"\r
+              "\t\tServiceData8.3..........0x%X\n"\r
+              "\t\tServiceData8.4..........0x%X\n"\r
+              "\t\tServiceData8.5..........0x%X\n"\r
+              "\t\tServiceData8.6..........0x%X\n"\r
+              "\t\tServiceData8.7..........0x%X\n"\r
+              "\t\tServiceData8.8..........0x%X\n"\r
+              "\t\tServiceData8.9..........0x%X\n"\r
+              "\t\tServiceData8.10.........0x%X\n"\r
+              "\t\tServiceData8.11.........0x%X\n"\r
+              "\t\tServiceData8.12.........0x%X\n"\r
+              "\t\tServiceData8.13.........0x%X\n"\r
+              "\t\tServiceData8.14.........0x%X\n"\r
+              "\t\tServiceData8.15.........0x%X\n"\r
+              "\t\tServiceData8.16.........0x%X\n"\r
+              "\t\tServiceData16.1.........0x%X\n"\r
+              "\t\tServiceData16.2.........0x%X\n"\r
+              "\t\tServiceData16.3.........0x%X\n"\r
+              "\t\tServiceData16.4.........0x%X\n"\r
+              "\t\tServiceData16.5.........0x%X\n"\r
+              "\t\tServiceData16.6.........0x%X\n"\r
+              "\t\tServiceData16.7.........0x%X\n"\r
+              "\t\tServiceData16.8.........0x%X\n"\r
+              "\t\tServiceData32.1.........0x%X\n"\r
+              "\t\tServiceData32.2.........0x%X\n"\r
+              "\t\tServiceData32.3.........0x%X\n"\r
+              "\t\tServiceData32.4.........0x%X\n"\r
+              "\t\tServiceData64.1.........0x%016" PRIx64 "\n"\r
+              "\t\tServiceData64.2.........0x%016" PRIx64 "\n"\r
+              "",\r
+              cl_ntoh64( p_sr->service_id ),\r
+              inet_ntop(AF_INET6, p_sr->service_gid.raw, gid_str,\r
+                       sizeof gid_str),\r
+              cl_ntoh16( p_sr->service_pkey ),\r
+              cl_ntoh32( p_sr->service_lease ),\r
+              buf_service_key,\r
+              buf_service_name,\r
+              p_sr->service_data8[0], p_sr->service_data8[1],\r
+              p_sr->service_data8[2], p_sr->service_data8[3],\r
+              p_sr->service_data8[4], p_sr->service_data8[5],\r
+              p_sr->service_data8[6], p_sr->service_data8[7],\r
+              p_sr->service_data8[8], p_sr->service_data8[9],\r
+              p_sr->service_data8[10], p_sr->service_data8[11],\r
+              p_sr->service_data8[12], p_sr->service_data8[13],\r
+              p_sr->service_data8[14], p_sr->service_data8[15],\r
+              cl_ntoh16( p_sr->service_data16[0] ),\r
+              cl_ntoh16( p_sr->service_data16[1] ),\r
+              cl_ntoh16( p_sr->service_data16[2] ),\r
+              cl_ntoh16( p_sr->service_data16[3] ),\r
+              cl_ntoh16( p_sr->service_data16[4] ),\r
+              cl_ntoh16( p_sr->service_data16[5] ),\r
+              cl_ntoh16( p_sr->service_data16[6] ),\r
+              cl_ntoh16( p_sr->service_data16[7] ),\r
+              cl_ntoh32( p_sr->service_data32[0] ),\r
+              cl_ntoh32( p_sr->service_data32[1] ),\r
+              cl_ntoh32( p_sr->service_data32[2] ),\r
+              cl_ntoh32( p_sr->service_data32[3] ),\r
+              cl_ntoh64( p_sr->service_data64[0] ),\r
+              cl_ntoh64( p_sr->service_data64[1] )\r
+             );\r
+}\r
+\r
+static void dump_inform_info_record(void *data)\r
+{\r
+       char   gid_str[INET6_ADDRSTRLEN];\r
+       char   gid_str2[INET6_ADDRSTRLEN];\r
+       ib_inform_info_record_t *p_iir = data;\r
+       uint32_t qpn;\r
+       uint8_t  resp_time_val;\r
+\r
+       ib_inform_info_get_qpn_resp_time(p_iir->inform_info.g_or_v.generic.qpn_resp_time_val, &qpn, &resp_time_val);\r
+\r
+       if (p_iir->inform_info.is_generic) {\r
+               printf("InformInfoRecord dump:\n"\r
+                      "\t\tRID\n"\r
+                      "\t\tSubscriberGID...........%s\n"\r
+                      "\t\tSubscriberEnum..........0x%X\n"\r
+                      "\t\tInformInfo dump:\n"\r
+                      "\t\tgid.....................%s\n"\r
+                      "\t\tlid_range_begin.........0x%X\n"\r
+                      "\t\tlid_range_end...........0x%X\n"\r
+                      "\t\tis_generic..............0x%X\n"\r
+                      "\t\tsubscribe...............0x%X\n"\r
+                      "\t\ttrap_type...............0x%X\n"\r
+                      "\t\ttrap_num................%u\n"\r
+                      "\t\tqpn.....................0x%06X\n"\r
+                      "\t\tresp_time_val...........0x%X\n"\r
+                      "\t\tnode_type...............0x%06X\n"\r
+                      "",\r
+                      inet_ntop(AF_INET6, p_iir->subscriber_gid.raw, gid_str,\r
+                               sizeof gid_str),\r
+                      cl_ntoh16( p_iir->subscriber_enum ),\r
+                      inet_ntop(AF_INET6, p_iir->inform_info.gid.raw, gid_str2,\r
+                               sizeof gid_str2),\r
+                      cl_ntoh16( p_iir->inform_info.lid_range_begin ),\r
+                      cl_ntoh16( p_iir->inform_info.lid_range_end ),\r
+                      p_iir->inform_info.is_generic,\r
+                      p_iir->inform_info.subscribe,\r
+                      cl_ntoh16( p_iir->inform_info.trap_type ),\r
+                      cl_ntoh16( p_iir->inform_info.g_or_v.generic.trap_num ),\r
+                      cl_ntoh32( qpn ),\r
+                      resp_time_val,\r
+                      cl_ntoh32(ib_inform_info_get_prod_type( &p_iir->inform_info ))\r
+                     );\r
+       } else {\r
+               printf("InformInfoRecord dump:\n"\r
+                      "\t\tRID\n"\r
+                      "\t\tSubscriberGID...........%s\n"\r
+                      "\t\tSubscriberEnum..........0x%X\n"\r
+                      "\t\tInformInfo dump:\n"\r
+                      "\t\tgid.....................%s\n"\r
+                      "\t\tlid_range_begin.........0x%X\n"\r
+                      "\t\tlid_range_end...........0x%X\n"\r
+                      "\t\tis_generic..............0x%X\n"\r
+                      "\t\tsubscribe...............0x%X\n"\r
+                      "\t\ttrap_type...............0x%X\n"\r
+                      "\t\tdev_id..................0x%X\n"\r
+                      "\t\tqpn.....................0x%06X\n"\r
+                      "\t\tresp_time_val...........0x%X\n"\r
+                      "\t\tvendor_id...............0x%06X\n"\r
+                      "",\r
+                      inet_ntop(AF_INET6, p_iir->subscriber_gid.raw, gid_str,\r
+                               sizeof gid_str),\r
+                      cl_ntoh16( p_iir->subscriber_enum ),\r
+                      inet_ntop(AF_INET6, p_iir->inform_info.gid.raw,\r
+                               gid_str2, sizeof gid_str2),\r
+                      cl_ntoh16( p_iir->inform_info.lid_range_begin ),\r
+                      cl_ntoh16( p_iir->inform_info.lid_range_end ),\r
+                      p_iir->inform_info.is_generic,\r
+                      p_iir->inform_info.subscribe,\r
+                      cl_ntoh16( p_iir->inform_info.trap_type ),\r
+                      cl_ntoh16( p_iir->inform_info.g_or_v.vend.dev_id ),\r
+                      cl_ntoh32( qpn ),\r
+                      resp_time_val,\r
+                      cl_ntoh32(ib_inform_info_get_prod_type( &p_iir->inform_info ))\r
+                     );\r
+       }\r
+}\r
+\r
+static void dump_one_link_record(void *data)\r
+{\r
+       ib_link_record_t *lr = data;\r
+       printf("LinkRecord dump:\n"\r
+              "\t\tFromLID....................%u\n"\r
+              "\t\tFromPort...................%u\n"\r
+              "\t\tToPort.....................%u\n"\r
+              "\t\tToLID......................%u\n",\r
+              cl_ntoh16(lr->from_lid), lr->from_port_num,\r
+              lr->to_port_num, cl_ntoh16(lr->to_lid));\r
+}\r
+\r
+static void dump_one_slvl_record(void *data)\r
+{\r
+       ib_slvl_table_record_t *slvl = data;\r
+       ib_slvl_table_t *t = &slvl->slvl_tbl;\r
+       printf("SL2VLTableRecord dump:\n"\r
+              "\t\tLID........................%u\n"\r
+              "\t\tInPort.....................%u\n"\r
+              "\t\tOutPort....................%u\n"\r
+              "\t\tSL: 0| 1| 2| 3| 4| 5| 6| 7| 8| 9|10|11|12|13|14|15|\n"\r
+              "\t\tVL:%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u"\r
+              "|%2u|%2u|%2u|\n",\r
+              cl_ntoh16(slvl->lid), slvl->in_port_num, slvl->out_port_num,\r
+              ib_slvl_table_get(t, 0), ib_slvl_table_get(t, 1),\r
+              ib_slvl_table_get(t, 2), ib_slvl_table_get(t, 3),\r
+              ib_slvl_table_get(t, 4), ib_slvl_table_get(t, 5),\r
+              ib_slvl_table_get(t, 6), ib_slvl_table_get(t, 7),\r
+              ib_slvl_table_get(t, 8), ib_slvl_table_get(t, 9),\r
+              ib_slvl_table_get(t, 10), ib_slvl_table_get(t, 11),\r
+              ib_slvl_table_get(t, 12), ib_slvl_table_get(t, 13),\r
+              ib_slvl_table_get(t, 14), ib_slvl_table_get(t, 15));\r
+}\r
+\r
+static void dump_one_vlarb_record(void *data)\r
+{\r
+       ib_vl_arb_table_record_t *vlarb = data;\r
+       ib_vl_arb_element_t *e = vlarb->vl_arb_tbl.vl_entry;\r
+       int i;\r
+       printf("VLArbTableRecord dump:\n"\r
+              "\t\tLID........................%u\n"\r
+              "\t\tPort.......................%u\n"\r
+              "\t\tBlock......................%u\n",\r
+              cl_ntoh16(vlarb->lid), vlarb->port_num, vlarb->block_num);\r
+       for (i = 0; i < 32 ; i += 16) {\r
+               printf("\t\tVL    :%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u|"\r
+                      "%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u|",\r
+                      e[i + 0].vl, e[i + 1].vl, e[i + 2].vl, e[i + 3].vl,\r
+                      e[i + 4].vl, e[i + 5].vl, e[i + 6].vl, e[i + 7].vl,\r
+                      e[i + 8].vl, e[i + 9].vl, e[i + 10].vl, e[i + 11].vl,\r
+                      e[i + 12].vl, e[i + 13].vl, e[i + 14].vl, e[i + 15].vl);\r
+               printf("\n\t\tWeight:%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u|"\r
+                      "%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u|",\r
+                      e[i + 0].weight, e[i + 1].weight, e[i + 2].weight,\r
+                      e[i + 3].weight, e[i + 4].weight, e[i + 5].weight,\r
+                      e[i + 6].weight, e[i + 7].weight, e[i + 8].weight,\r
+                      e[i + 9].weight, e[i + 10].weight, e[i + 11].weight,\r
+                      e[i + 12].weight, e[i + 13].weight, e[i + 14].weight,\r
+                      e[i + 15].weight);\r
+               printf("\n");\r
+       }\r
+}\r
+\r
+static void dump_one_pkey_tbl_record(void *data)\r
+{\r
+       ib_pkey_table_record_t *pktr = data;\r
+       ib_net16_t *p = pktr->pkey_tbl.pkey_entry;\r
+       int i;\r
+       printf("PKeyTableRecord dump:\n"\r
+              "\t\tLID........................%u\n"\r
+              "\t\tPort.......................%u\n"\r
+              "\t\tBlock......................%u\n"\r
+              "\t\tPKey Table:\n",\r
+              cl_ntoh16(pktr->lid), pktr->port_num, pktr->block_num);\r
+       for (i = 0; i < 32 ; i += 8)\r
+               printf("\t\t0x%04x 0x%04x 0x%04x 0x%04x"\r
+                      " 0x%04x 0x%04x 0x%04x 0x%04x\n",\r
+                      cl_ntoh16(p[i + 0]), cl_ntoh16(p[i + 1]),\r
+                      cl_ntoh16(p[i + 2]), cl_ntoh16(p[i + 3]),\r
+                      cl_ntoh16(p[i + 4]), cl_ntoh16(p[i + 5]),\r
+                      cl_ntoh16(p[i + 6]), cl_ntoh16(p[i + 7]));\r
+       printf("\n");\r
+}\r
+\r
+static void dump_one_lft_record(void *data)\r
+{\r
+       ib_lft_record_t *lftr = data;\r
+       unsigned block = cl_ntoh16(lftr->block_num);\r
+       int i;\r
+       printf("LFT Record dump:\n"\r
+              "\t\tLID........................%u\n"\r
+              "\t\tBlock......................%u\n"\r
+              "\t\tLFT:\n\t\tLID\tPort Number\n",\r
+              cl_ntoh16(lftr->lid), block);\r
+       for (i = 0; i < 64 ; i++)\r
+               printf("\t\t%u\t%u\n", block*64 + i, lftr->lft[i]);\r
+       printf("\n");\r
+}\r
+\r
+static void dump_one_mft_record(void *data)\r
+{\r
+       ib_mft_record_t *mftr = data;\r
+       unsigned position = cl_ntoh16(mftr->position_block_num) >> 12;\r
+       unsigned block = cl_ntoh16(mftr->position_block_num) &\r
+                        IB_MCAST_BLOCK_ID_MASK_HO;\r
+       int i;\r
+       printf("MFT Record dump:\n"\r
+              "\t\tLID........................%u\n"\r
+              "\t\tPosition...................%u\n"\r
+              "\t\tBlock......................%u\n"\r
+               "\t\tMFT:\n\t\tMLID\tPort Mask\n",\r
+              cl_ntoh16(mftr->lid), position, block);\r
+       for (i = 0; i < IB_MCAST_BLOCK_SIZE; i++)\r
+               printf("\t\t0x%x\t0x%x\n", IB_LID_MCAST_START_HO + block*64 + i,\r
+                      cl_ntoh16(mftr->mft[i]));\r
+       printf("\n");\r
+}\r
+static void dump_results(osmv_query_res_t *r, void (*dump_func)(void *))\r
+{\r
+       int i;\r
+       for (i = 0; i < r->result_cnt; i++) {\r
+               void *data = osmv_get_query_result(r->p_result_madw, i);\r
+               dump_func(data);\r
+       }\r
+}\r
+\r
+static void\r
+return_mad(void)\r
+{\r
+       /*\r
+        * Return the IB query MAD to the pool as necessary.\r
+        */\r
+       if (result.p_result_madw != NULL) {\r
+               osm_mad_pool_put(&mad_pool, result.p_result_madw);\r
+               result.p_result_madw = NULL;\r
+       }\r
+}\r
+\r
+/**\r
+ * Get any record(s)\r
+ */\r
+static ib_api_status_t\r
+get_any_records(osm_bind_handle_t bind_handle,\r
+               ib_net16_t attr_id, ib_net32_t attr_mod, ib_net64_t comp_mask,\r
+               void *attr, ib_net16_t attr_offset,\r
+               ib_net64_t sm_key)\r
+{\r
+       ib_api_status_t   status;\r
+       osmv_query_req_t  req;\r
+       osmv_user_query_t user;\r
+\r
+       memset(&req, 0, sizeof(req));\r
+       memset(&user, 0, sizeof(user));\r
+\r
+       user.attr_id = attr_id;\r
+       user.attr_offset = attr_offset;\r
+       user.attr_mod = attr_mod;\r
+       user.comp_mask = comp_mask;\r
+       user.p_attr = attr;\r
+\r
+       req.query_type = OSMV_QUERY_USER_DEFINED;\r
+       req.timeout_ms = sa_timeout_ms;\r
+       req.retry_cnt = 1;\r
+       req.flags = OSM_SA_FLAGS_SYNC;\r
+       req.query_context = NULL;\r
+       req.pfn_query_cb = query_res_cb;\r
+       req.p_query_input = &user;\r
+       req.sm_key = sm_key;\r
+\r
+       if ((status = osmv_query_sa(bind_handle, &req)) != IB_SUCCESS) {\r
+               fprintf(stderr, "Query SA failed: %s\n",\r
+                       ib_get_err_str(status));\r
+               return status;\r
+       }\r
+\r
+       if (result.status != IB_SUCCESS) {\r
+               fprintf(stderr, "Query result returned: %s\n",\r
+                       ib_get_err_str(result.status));\r
+               return result.status;\r
+       }\r
+\r
+       return status;\r
+}\r
+\r
+/**\r
+ * Get all the records available for requested query type.\r
+ */\r
+static ib_api_status_t\r
+get_all_records(osm_bind_handle_t bind_handle,\r
+               ib_net16_t query_id,\r
+               ib_net16_t attr_offset,\r
+               int trusted)\r
+{\r
+       return get_any_records(bind_handle, query_id, 0, 0, NULL, attr_offset,\r
+                              trusted ? smkey : 0);\r
+}\r
+\r
+/**\r
+ * return the lid from the node descriptor (name) supplied\r
+ */\r
+static ib_api_status_t\r
+get_lid_from_name(osm_bind_handle_t bind_handle, const char *name, ib_net16_t *lid)\r
+{\r
+       int               i = 0;\r
+       ib_node_record_t *node_record = NULL;\r
+       ib_node_info_t   *p_ni = NULL;\r
+       ib_net16_t        attr_offset = ib_get_attr_offset(sizeof(*node_record));\r
+       ib_api_status_t   status;\r
+\r
+       status = get_all_records(bind_handle, IB_MAD_ATTR_NODE_RECORD, attr_offset, 0);\r
+       if (status != IB_SUCCESS)\r
+               return (status);\r
+\r
+       for (i = 0; i < result.result_cnt; i++) {\r
+               node_record = osmv_get_query_node_rec(result.p_result_madw, i);\r
+               p_ni = &(node_record->node_info);\r
+               if (name && strncmp(name, (char *)node_record->node_desc.description,\r
+                                   sizeof(node_record->node_desc.description)) == 0) {\r
+                       *lid = cl_ntoh16(node_record->lid);\r
+                       break;\r
+               }\r
+       }\r
+       return_mad();\r
+       return (status);\r
+}\r
+\r
+static ib_net16_t\r
+get_lid(osm_bind_handle_t bind_handle, const char * name)\r
+{\r
+       ib_net16_t rc_lid = 0;\r
+\r
+       if (!name)\r
+               return(0);\r
+       if (isalpha(name[0]))\r
+               assert(get_lid_from_name(bind_handle, name, &rc_lid) == IB_SUCCESS);\r
+       else\r
+               rc_lid = atoi(name);\r
+       if (rc_lid == 0)\r
+               fprintf(stderr, "Failed to find lid for \"%s\"\n", name);\r
+        return (rc_lid);\r
+}\r
+\r
+static int parse_lid_and_ports(osm_bind_handle_t bind_handle,\r
+                              char *str, int *lid, int *port1, int *port2)\r
+{\r
+       char *p, *e;\r
+\r
+       if (port1) *port1 = -1;\r
+       if (port2) *port2 = -1;\r
+\r
+       p = strchr(str, '/');\r
+       if (p) *p = '\0';\r
+       if (lid)\r
+               *lid = get_lid(bind_handle, str);\r
+\r
+       if (!p)\r
+               return 0;\r
+       str = p + 1;\r
+       p = strchr(str, '/');\r
+       if (p) *p = '\0';\r
+       if (port1) {\r
+               *port1 = strtoul(str, &e, 0);\r
+               if (e == str)\r
+                       *port1 = -1;\r
+       }\r
+\r
+       if (!p)\r
+               return 0;\r
+       str = p + 1;\r
+       if (port2) {\r
+               *port2 = strtoul(str, &e, 0);\r
+               if (e == str)\r
+                       *port2 = -1;\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+/*\r
+ * Get the portinfo records available with IsSM or IsSMdisabled CapabilityMask bit on.\r
+ */\r
+static ib_api_status_t\r
+get_issm_records(osm_bind_handle_t bind_handle, ib_net32_t capability_mask)\r
+{\r
+       ib_portinfo_record_t attr;\r
+\r
+       memset( &attr, 0, sizeof ( attr ) );\r
+       attr.port_info.capability_mask = capability_mask;\r
+\r
+       return get_any_records(bind_handle, IB_MAD_ATTR_PORTINFO_RECORD,\r
+                              cl_hton32(1 << 31), IB_PIR_COMPMASK_CAPMASK,\r
+                              &attr,\r
+                              ib_get_attr_offset(sizeof(ib_portinfo_record_t)),\r
+                              0);\r
+}\r
+\r
+static ib_api_status_t\r
+print_node_records(osm_bind_handle_t bind_handle)\r
+{\r
+       int               i = 0;\r
+       ib_node_record_t *node_record = NULL;\r
+       ib_net16_t        attr_offset = ib_get_attr_offset(sizeof(*node_record));\r
+       ib_api_status_t   status;\r
+\r
+       status  = get_all_records(bind_handle, IB_MAD_ATTR_NODE_RECORD, attr_offset, 0);\r
+       if (status != IB_SUCCESS)\r
+               return (status);\r
+\r
+       if (node_print_desc == ALL_DESC) {\r
+               printf("   LID \"name\"\n");\r
+               printf("================\n");\r
+       }\r
+       for (i = 0; i < result.result_cnt; i++) {\r
+               node_record = osmv_get_query_node_rec(result.p_result_madw, i);\r
+               if (node_print_desc == ALL_DESC) {\r
+                       print_node_desc(node_record);\r
+               } else if (node_print_desc == NAME_OF_LID) {\r
+                       if (requested_lid == cl_ntoh16(node_record->lid)) {\r
+                               print_node_record(node_record);\r
+                       }\r
+               } else if (node_print_desc == NAME_OF_GUID) {\r
+                       ib_node_info_t *p_ni = &(node_record->node_info);\r
+\r
+                       if (requested_guid == cl_ntoh64(p_ni->port_guid)) {\r
+                               print_node_record(node_record);\r
+                       }\r
+               } else {\r
+                       if (!requested_name ||\r
+                           (strncmp(requested_name,\r
+                                    (char *)node_record->node_desc.description,\r
+                                    sizeof(node_record->node_desc.description)) == 0)) {\r
+                               print_node_record(node_record);\r
+                               if (node_print_desc == UNIQUE_LID_ONLY) {\r
+                                       return_mad();\r
+                                       exit(0);\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+       return_mad();\r
+       return (status);\r
+}\r
+\r
+static ib_api_status_t\r
+get_print_path_rec_lid(osm_bind_handle_t bind_handle,\r
+                      ib_net16_t src_lid,\r
+                      ib_net16_t dst_lid)\r
+{\r
+       osmv_query_req_t      req;\r
+       osmv_lid_pair_t       lid_pair;\r
+       ib_api_status_t       status;\r
+\r
+       lid_pair.src_lid = cl_hton16(src_lid);\r
+       lid_pair.dest_lid = cl_hton16(dst_lid);\r
+\r
+       memset( &req, 0, sizeof( req ) );\r
+\r
+       req.query_type = OSMV_QUERY_PATH_REC_BY_LIDS;\r
+       req.timeout_ms = sa_timeout_ms;\r
+       req.retry_cnt = 1;\r
+       req.flags = OSM_SA_FLAGS_SYNC;\r
+       req.query_context = NULL;\r
+       req.pfn_query_cb = query_res_cb;\r
+       req.p_query_input = (void *)&lid_pair;\r
+       req.sm_key = 0;\r
+\r
+       if ((status = osmv_query_sa(bind_handle, &req)) != IB_SUCCESS) {\r
+               fprintf(stderr, "ERROR: Query SA failed: %s\n",\r
+                       ib_get_err_str(status));\r
+               return (status);\r
+       }\r
+       if (result.status != IB_SUCCESS) {\r
+               fprintf(stderr, "ERROR: Query result returned: %s\n",\r
+                       ib_get_err_str(result.status));\r
+               return (result.status);\r
+       }\r
+       status = result.status;\r
+       dump_results(&result, dump_path_record);\r
+       return_mad();\r
+       return (status);\r
+}\r
+\r
+static ib_api_status_t\r
+get_print_path_rec_gid(osm_bind_handle_t bind_handle,\r
+                      const ib_gid_t *src_gid,\r
+                      const ib_gid_t *dst_gid)\r
+{\r
+       osmv_query_req_t      req;\r
+       osmv_gid_pair_t       gid_pair;\r
+       ib_api_status_t       status;\r
+\r
+       gid_pair.src_gid = *src_gid;\r
+       gid_pair.dest_gid = *dst_gid;\r
+\r
+       memset( &req, 0, sizeof( req ) );\r
+\r
+       req.query_type = OSMV_QUERY_PATH_REC_BY_GIDS;\r
+       req.timeout_ms = sa_timeout_ms;\r
+       req.retry_cnt = 1;\r
+       req.flags = OSM_SA_FLAGS_SYNC;\r
+       req.query_context = NULL;\r
+       req.pfn_query_cb = query_res_cb;\r
+       req.p_query_input = (void *)&gid_pair;\r
+       req.sm_key = 0;\r
+\r
+       if ((status = osmv_query_sa(bind_handle, &req)) != IB_SUCCESS) {\r
+               fprintf(stderr, "ERROR: Query SA failed: %s\n",\r
+                       ib_get_err_str(status));\r
+               return (status);\r
+       }\r
+       if (result.status != IB_SUCCESS) {\r
+               fprintf(stderr, "ERROR: Query result returned: %s\n",\r
+                       ib_get_err_str(result.status));\r
+               return (result.status);\r
+       }\r
+       status = result.status;\r
+       dump_results(&result, dump_path_record);\r
+       return_mad();\r
+       return (status);\r
+}\r
+\r
+static ib_api_status_t\r
+get_print_class_port_info(osm_bind_handle_t bind_handle)\r
+{\r
+       osmv_query_req_t      req;\r
+       ib_api_status_t       status;\r
+\r
+       memset( &req, 0, sizeof( req ) );\r
+\r
+       req.query_type = OSMV_QUERY_CLASS_PORT_INFO;\r
+       req.timeout_ms = sa_timeout_ms;\r
+       req.retry_cnt = 1;\r
+       req.flags = OSM_SA_FLAGS_SYNC;\r
+       req.query_context = NULL;\r
+       req.pfn_query_cb = query_res_cb;\r
+       req.p_query_input = NULL;\r
+       req.sm_key = 0;\r
+\r
+       if ((status = osmv_query_sa(bind_handle, &req)) != IB_SUCCESS) {\r
+               fprintf(stderr, "ERROR: Query SA failed: %s\n",\r
+                       ib_get_err_str(status));\r
+               return (status);\r
+       }\r
+       if (result.status != IB_SUCCESS) {\r
+               fprintf(stderr, "ERROR: Query result returned: %s\n",\r
+                       ib_get_err_str(result.status));\r
+               return (result.status);\r
+       }\r
+       status = result.status;\r
+       dump_results(&result, dump_class_port_info);\r
+       return_mad();\r
+       return (status);\r
+}\r
+\r
+static ib_api_status_t\r
+print_path_records(osm_bind_handle_t bind_handle)\r
+{\r
+       ib_net16_t attr_offset = ib_get_attr_offset(sizeof(ib_path_rec_t));\r
+       ib_api_status_t status;\r
+\r
+       status = get_all_records(bind_handle, IB_MAD_ATTR_PATH_RECORD, attr_offset, 0);\r
+       if (status != IB_SUCCESS)\r
+               return (status);\r
+\r
+       dump_results(&result, dump_path_record);\r
+       return_mad();\r
+       return (status);\r
+}\r
+\r
+static ib_api_status_t\r
+print_portinfo_records(osm_bind_handle_t bind_handle)\r
+{\r
+       ib_api_status_t       status;\r
+\r
+       /* First, get IsSM records */\r
+       status = get_issm_records(bind_handle, IB_PORT_CAP_IS_SM);\r
+       if (status != IB_SUCCESS)\r
+               return (status);\r
+\r
+       printf("IsSM ports\n");\r
+       dump_results(&result, dump_portinfo_record);\r
+       return_mad();\r
+\r
+       /* Now, get IsSMdisabled records */\r
+       status = get_issm_records(bind_handle, IB_PORT_CAP_SM_DISAB);\r
+       if (status != IB_SUCCESS)\r
+               return (status);\r
+\r
+       printf("\nIsSMdisabled ports\n");\r
+       dump_results(&result, dump_portinfo_record);\r
+       return_mad();\r
+\r
+       return (status);\r
+}\r
+\r
+static ib_api_status_t\r
+print_multicast_member_records(osm_bind_handle_t bind_handle)\r
+{\r
+       osmv_query_res_t  mc_group_result;\r
+       ib_api_status_t   status;\r
+\r
+       status = get_all_records(bind_handle, IB_MAD_ATTR_MCMEMBER_RECORD,\r
+                                ib_get_attr_offset(sizeof(ib_member_rec_t)), 1);\r
+       if (status != IB_SUCCESS)\r
+               return (status);\r
+\r
+       mc_group_result = result;\r
+\r
+       status  = get_all_records(bind_handle, IB_MAD_ATTR_NODE_RECORD,\r
+                                 ib_get_attr_offset(sizeof(ib_node_record_t)), 0);\r
+       if (status != IB_SUCCESS)\r
+               goto return_mc;\r
+\r
+       dump_results(&mc_group_result, dump_multicast_member_record);\r
+       return_mad();\r
+\r
+return_mc:\r
+       /* return_mad for the mc_group_result */\r
+       if (mc_group_result.p_result_madw != NULL) {\r
+               osm_mad_pool_put(&mad_pool, mc_group_result.p_result_madw);\r
+               mc_group_result.p_result_madw = NULL;\r
+       }\r
+\r
+       return (status);\r
+}\r
+\r
+static ib_api_status_t\r
+print_multicast_group_records(osm_bind_handle_t bind_handle)\r
+{\r
+       ib_api_status_t   status;\r
+\r
+       status = get_all_records(bind_handle, IB_MAD_ATTR_MCMEMBER_RECORD,\r
+                                ib_get_attr_offset(sizeof(ib_member_rec_t)), 0);\r
+       if (status != IB_SUCCESS)\r
+               return (status);\r
+\r
+       dump_results(&result, dump_multicast_group_record);\r
+       return_mad();\r
+       return (status);\r
+}\r
+\r
+static ib_api_status_t\r
+print_service_records(osm_bind_handle_t bind_handle)\r
+{\r
+       ib_net16_t attr_offset = ib_get_attr_offset(sizeof(ib_service_record_t));\r
+       ib_api_status_t status;\r
+\r
+       status = get_all_records(bind_handle, IB_MAD_ATTR_SERVICE_RECORD, attr_offset, 0);\r
+       if (status != IB_SUCCESS)\r
+               return (status);\r
+\r
+       dump_results(&result, dump_service_record);\r
+       return_mad();\r
+       return (status);\r
+}\r
+\r
+static ib_api_status_t\r
+print_inform_info_records(osm_bind_handle_t bind_handle)\r
+{\r
+       ib_net16_t attr_offset = ib_get_attr_offset(sizeof(ib_inform_info_record_t));\r
+       ib_api_status_t status;\r
+\r
+       status = get_all_records(bind_handle, IB_MAD_ATTR_INFORM_INFO_RECORD, attr_offset, 0);\r
+       if (status != IB_SUCCESS)\r
+               return (status);\r
+\r
+       dump_results(&result, dump_inform_info_record);\r
+       return_mad();\r
+       return (status);\r
+}\r
+\r
+static ib_api_status_t\r
+print_link_records(osm_bind_handle_t bind_handle, int argc, char *argv[])\r
+{\r
+       ib_link_record_t lr;\r
+       ib_net64_t comp_mask = 0;\r
+       int from_lid = 0, to_lid = 0, from_port = -1, to_port = -1;\r
+       ib_api_status_t status;\r
+\r
+       if (argc > 0)\r
+               parse_lid_and_ports(bind_handle, argv[0],\r
+                                   &from_lid, &from_port, NULL);\r
+\r
+       if (argc > 1)\r
+               parse_lid_and_ports(bind_handle, argv[1],\r
+                                   &to_lid, &to_port, NULL);\r
+\r
+       memset(&lr, 0, sizeof(lr));\r
+\r
+       if (from_lid > 0) {\r
+               lr.from_lid = cl_hton16(from_lid);\r
+               comp_mask |= IB_LR_COMPMASK_FROM_LID;\r
+       }\r
+       if (from_port >= 0) {\r
+               lr.from_port_num = from_port;\r
+               comp_mask |= IB_LR_COMPMASK_FROM_PORT;\r
+       }\r
+       if (to_lid > 0) {\r
+               lr.to_lid = cl_hton16(to_lid);\r
+               comp_mask |= IB_LR_COMPMASK_TO_LID;\r
+       }\r
+       if (to_port >= 0) {\r
+               lr.to_port_num = to_port;\r
+               comp_mask |= IB_LR_COMPMASK_TO_PORT;\r
+       }\r
+\r
+       status = get_any_records(bind_handle, IB_MAD_ATTR_LINK_RECORD, 0,\r
+                                comp_mask, &lr,\r
+                                ib_get_attr_offset(sizeof(lr)), 0);\r
+       if (status != IB_SUCCESS)\r
+               return status;\r
+\r
+       dump_results(&result, dump_one_link_record);\r
+       return_mad();\r
+       return status;\r
+}\r
+\r
+static int\r
+print_sl2vl_records(const struct query_cmd *q, osm_bind_handle_t bind_handle,\r
+                   int argc, char *argv[])\r
+{\r
+       ib_slvl_table_record_t slvl;\r
+       ib_net64_t comp_mask = 0;\r
+       int lid = 0, in_port = -1, out_port = -1;\r
+       ib_api_status_t status;\r
+\r
+       if (argc > 0)\r
+               parse_lid_and_ports(bind_handle, argv[0],\r
+                                   &lid, &in_port, &out_port);\r
+\r
+       memset(&slvl, 0, sizeof(slvl));\r
+\r
+       if (lid > 0) {\r
+               slvl.lid = cl_hton16(lid);\r
+               comp_mask |= IB_SLVL_COMPMASK_LID;\r
+       }\r
+       if (in_port >= 0) {\r
+               slvl.in_port_num = in_port;\r
+               comp_mask |= IB_SLVL_COMPMASK_IN_PORT;\r
+       }\r
+       if (out_port >= 0) {\r
+               slvl.out_port_num = out_port;\r
+               comp_mask |= IB_SLVL_COMPMASK_OUT_PORT;\r
+       }\r
+\r
+       status = get_any_records(bind_handle, IB_MAD_ATTR_SLVL_RECORD, 0,\r
+                                comp_mask, &slvl,\r
+                                ib_get_attr_offset(sizeof(slvl)), 0);\r
+       if (status != IB_SUCCESS)\r
+               return status;\r
+\r
+       dump_results(&result, dump_one_slvl_record);\r
+       return_mad();\r
+       return status;\r
+}\r
+\r
+static int\r
+print_vlarb_records(const struct query_cmd *q, osm_bind_handle_t bind_handle,\r
+                   int argc, char *argv[])\r
+{\r
+       ib_vl_arb_table_record_t vlarb;\r
+       ib_net64_t comp_mask = 0;\r
+       int lid = 0, port = -1, block = -1;\r
+       ib_api_status_t status;\r
+\r
+       if (argc > 0)\r
+               parse_lid_and_ports(bind_handle, argv[0],\r
+                                   &lid, &port, &block);\r
+\r
+       memset(&vlarb, 0, sizeof(vlarb));\r
+\r
+       if (lid > 0) {\r
+               vlarb.lid = cl_hton16(lid);\r
+               comp_mask |= IB_VLA_COMPMASK_LID;\r
+       }\r
+       if (port >= 0) {\r
+               vlarb.port_num = port;\r
+               comp_mask |= IB_VLA_COMPMASK_OUT_PORT;\r
+       }\r
+       if (block >= 0) {\r
+               vlarb.block_num = block;\r
+               comp_mask |= IB_VLA_COMPMASK_BLOCK;\r
+       }\r
+\r
+       status = get_any_records(bind_handle, IB_MAD_ATTR_VLARB_RECORD, 0,\r
+                                comp_mask, &vlarb,\r
+                                ib_get_attr_offset(sizeof(vlarb)), 0);\r
+       if (status != IB_SUCCESS)\r
+               return status;\r
+\r
+       dump_results(&result, dump_one_vlarb_record);\r
+       return_mad();\r
+       return status;\r
+}\r
+\r
+static int\r
+print_pkey_tbl_records(const struct query_cmd *q, osm_bind_handle_t bind_handle,\r
+                      int argc, char *argv[])\r
+{\r
+       ib_pkey_table_record_t pktr;\r
+       ib_net64_t comp_mask = 0;\r
+       int lid = 0, port = -1, block = -1;\r
+       ib_api_status_t status;\r
+\r
+       if (argc > 0)\r
+               parse_lid_and_ports(bind_handle, argv[0],\r
+                                   &lid, &port, &block);\r
+\r
+       memset(&pktr, 0, sizeof(pktr));\r
+\r
+       if (lid > 0) {\r
+               pktr.lid = cl_hton16(lid);\r
+               comp_mask |= IB_PKEY_COMPMASK_LID;\r
+       }\r
+       if (port >= 0) {\r
+               pktr.port_num = port;\r
+               comp_mask |= IB_PKEY_COMPMASK_PORT;\r
+       }\r
+       if (block >= 0) {\r
+               pktr.block_num = block;\r
+               comp_mask |= IB_PKEY_COMPMASK_BLOCK;\r
+       }\r
+\r
+       status = get_any_records(bind_handle, IB_MAD_ATTR_PKEY_TBL_RECORD, 0,\r
+                                comp_mask, &pktr,\r
+                                ib_get_attr_offset(sizeof(pktr)), smkey);\r
+       if (status != IB_SUCCESS)\r
+               return status;\r
+\r
+       dump_results(&result, dump_one_pkey_tbl_record);\r
+       return_mad();\r
+       return status;\r
+}\r
+\r
+static int\r
+print_lft_records(const struct query_cmd *q, osm_bind_handle_t bind_handle,\r
+                 int argc, char *argv[])\r
+{\r
+       ib_lft_record_t lftr;\r
+       ib_net64_t comp_mask = 0;\r
+       int lid = 0, block = -1;\r
+       ib_api_status_t status;\r
+\r
+       if (argc > 0)\r
+               parse_lid_and_ports(bind_handle, argv[0],\r
+                                   &lid, &block, NULL);\r
+\r
+       memset(&lftr, 0, sizeof(lftr));\r
+\r
+       if (lid > 0) {\r
+               lftr.lid = cl_hton16(lid);\r
+               comp_mask |= IB_LFTR_COMPMASK_LID;\r
+       }\r
+       if (block >= 0) {\r
+               lftr.block_num = cl_hton16(block);\r
+               comp_mask |= IB_LFTR_COMPMASK_BLOCK;\r
+       }\r
+\r
+       status = get_any_records(bind_handle, IB_MAD_ATTR_LFT_RECORD, 0,\r
+                                comp_mask, &lftr,\r
+                                ib_get_attr_offset(sizeof(lftr)), 0);\r
+       if (status != IB_SUCCESS)\r
+               return status;\r
+\r
+       dump_results(&result, dump_one_lft_record);\r
+       return_mad();\r
+       return status;\r
+}\r
+\r
+static int\r
+print_mft_records(const struct query_cmd *q, osm_bind_handle_t bind_handle,\r
+                 int argc, char *argv[])\r
+{\r
+       ib_mft_record_t mftr;\r
+       ib_net64_t comp_mask = 0;\r
+       int lid = 0, block = -1, position = -1;\r
+       ib_api_status_t status;\r
+\r
+       if (argc > 0)\r
+               parse_lid_and_ports(bind_handle, argv[0],\r
+                                  &lid, &position, &block);\r
+\r
+       memset(&mftr, 0, sizeof(mftr));\r
+\r
+       if (lid > 0) {\r
+               mftr.lid = cl_hton16(lid);\r
+               comp_mask |= IB_MFTR_COMPMASK_LID;\r
+       }\r
+       if (position >= 0) {\r
+               mftr.position_block_num = cl_hton16(position << 12);\r
+               comp_mask |= IB_MFTR_COMPMASK_POSITION;\r
+       }\r
+       if (block >= 0) {\r
+               mftr.position_block_num |= cl_hton16(block & IB_MCAST_BLOCK_ID_MASK_HO);\r
+               comp_mask |= IB_MFTR_COMPMASK_BLOCK;\r
+       }\r
+\r
+       status = get_any_records(bind_handle, IB_MAD_ATTR_MFT_RECORD, 0,\r
+                                comp_mask, &mftr,\r
+                                ib_get_attr_offset(sizeof(mftr)), 0);\r
+       if (status != IB_SUCCESS)\r
+               return status;\r
+\r
+       dump_results(&result, dump_one_mft_record);\r
+       return_mad();\r
+       return status;\r
+}\r
+\r
+static osm_bind_handle_t\r
+get_bind_handle(void)\r
+{\r
+       uint32_t           i = 0;\r
+       uint64_t           port_guid = (uint64_t)-1;\r
+       osm_bind_handle_t  bind_handle;\r
+       ib_api_status_t    status;\r
+       ib_port_attr_t     attr_array[MAX_PORTS];\r
+       uint32_t           num_ports = MAX_PORTS;\r
+       uint32_t           ca_name_index = 0;\r
+\r
+       complib_init();\r
+\r
+       osm_log_construct(&log_osm);\r
+       if ((status = osm_log_init_v2(&log_osm, TRUE, 0x0001, NULL,\r
+                                     0, TRUE)) != IB_SUCCESS) {\r
+               fprintf(stderr, "Failed to init osm_log: %s\n",\r
+                       ib_get_err_str(status));\r
+               exit(-1);\r
+       }\r
+       osm_log_set_level(&log_osm, OSM_LOG_NONE);\r
+       if (osm_debug)\r
+               osm_log_set_level(&log_osm, OSM_LOG_DEFAULT_LEVEL);\r
+\r
+        vendor = osm_vendor_new(&log_osm, sa_timeout_ms);\r
+       osm_mad_pool_construct(&mad_pool);\r
+       if ((status = osm_mad_pool_init(&mad_pool)) != IB_SUCCESS) {\r
+               fprintf(stderr, "Failed to init mad pool: %s\n",\r
+                       ib_get_err_str(status));\r
+               exit(-1);\r
+       }\r
+\r
+       if ((status = osm_vendor_get_all_port_attr(vendor, attr_array, &num_ports)) != IB_SUCCESS) {\r
+               fprintf(stderr, "Failed to get port attributes: %s\n",\r
+                       ib_get_err_str(status));\r
+               exit(-1);\r
+       }\r
+\r
+       for (i = 0; i < num_ports; i++) {\r
+               if (i > 1 && cl_ntoh64(attr_array[i].port_guid)\r
+                               != (cl_ntoh64(attr_array[i-1].port_guid) + 1))\r
+                       ca_name_index++;\r
+               if (sa_port_num && sa_port_num != attr_array[i].port_num)\r
+                       continue;\r
+               if (sa_hca_name\r
+                && strcmp(sa_hca_name, vendor->ca_names[ca_name_index]) != 0)\r
+                       continue;\r
+               if (attr_array[i].link_state == IB_LINK_ACTIVE) {\r
+                       port_guid = attr_array[i].port_guid;\r
+                       break;\r
+               }\r
+       }\r
+\r
+       if (port_guid == (uint64_t)-1) {\r
+               fprintf(stderr, "Failed to find active port, check port status with \"ibstat\"\n");\r
+               exit(-1);\r
+       }\r
+\r
+       bind_handle = osmv_bind_sa(vendor, &mad_pool, port_guid);\r
+\r
+       if (bind_handle == OSM_BIND_INVALID_HANDLE) {\r
+               fprintf(stderr, "Failed to bind to SA\n");\r
+               exit(-1);\r
+       }\r
+       return (bind_handle);\r
+}\r
+\r
+static void\r
+clean_up(void)\r
+{\r
+       osm_mad_pool_destroy(&mad_pool);\r
+       osm_vendor_delete(&vendor);\r
+}\r
+\r
+static const struct query_cmd query_cmds[] = {\r
+       { "ClassPortInfo", "CPI", IB_MAD_ATTR_CLASS_PORT_INFO, },\r
+       { "NodeRecord", "NR", IB_MAD_ATTR_NODE_RECORD, },\r
+       { "PortInfoRecord", "PIR", IB_MAD_ATTR_PORTINFO_RECORD, },\r
+       { "SL2VLTableRecord", "SL2VL", IB_MAD_ATTR_SLVL_RECORD,\r
+         "[[lid]/[in_port]/[out_port]]",\r
+          print_sl2vl_records },\r
+       { "PKeyTableRecord", "PKTR", IB_MAD_ATTR_PKEY_TBL_RECORD,\r
+         "[[lid]/[port]/[block]]",\r
+          print_pkey_tbl_records },\r
+       { "VLArbitrationTableRecord", "VLAR", IB_MAD_ATTR_VLARB_RECORD,\r
+         "[[lid]/[port]/[block]]",\r
+          print_vlarb_records },\r
+       { "InformInfoRecord", "IIR", IB_MAD_ATTR_INFORM_INFO_RECORD, },\r
+       { "LinkRecord", "LR", IB_MAD_ATTR_LINK_RECORD,\r
+         "[[from_lid]/[from_port]] [[to_lid]/[to_port]]", },\r
+       { "ServiceRecord", "SR", IB_MAD_ATTR_SERVICE_RECORD, },\r
+       { "PathRecord", "PR", IB_MAD_ATTR_PATH_RECORD, },\r
+       { "MCMemberRecord", "MCMR", IB_MAD_ATTR_MCMEMBER_RECORD, },\r
+       { "LFTRecord", "LFTR", IB_MAD_ATTR_LFT_RECORD, "[[lid]/[block]]",\r
+         print_lft_records },\r
+       { "MFTRecord", "MFTR", IB_MAD_ATTR_MFT_RECORD,\r
+         "[[mlid]/[position]/[block]]",\r
+         print_mft_records },\r
+       { 0 }\r
+};\r
+\r
+static const struct query_cmd *find_query(const char *name)\r
+{\r
+       const struct query_cmd *q;\r
+       unsigned len = strlen(name);\r
+\r
+       for (q = query_cmds; q->name; q++)\r
+               if (!strncasecmp(name, q->name, len) ||\r
+                   (q->alias && !strncasecmp(name, q->alias, len)))\r
+                       return q;\r
+\r
+       return NULL;\r
+}\r
+\r
+static void\r
+usage(void)\r
+{\r
+       const struct query_cmd *q;\r
+\r
+       fprintf(stderr, "Usage: %s [-h -d -p -N] [--list | -D] [-S -I -L -l -G"\r
+               " -O -U -c -s -g -m --src-to-dst <src:dst> --sgid-to-dgid <src-dst> "\r
+               "-C <ca_name> -P <ca_port> -t(imeout) <msec>] [query-name] [<name> | <lid> | <guid>]\n",\r
+               argv0);\r
+       fprintf(stderr, "   Queries node records by default\n");\r
+       fprintf(stderr, "   -d enable debugging\n");\r
+       fprintf(stderr, "   -p get PathRecord info\n");\r
+       fprintf(stderr, "   -N get NodeRecord info\n");\r
+       fprintf(stderr, "   --list | -D the node desc of the CA's\n");\r
+       fprintf(stderr, "   -S get ServiceRecord info\n");\r
+       fprintf(stderr, "   -I get InformInfoRecord (subscription) info\n");\r
+       fprintf(stderr, "   -L return the Lids of the name specified\n");\r
+       fprintf(stderr, "   -l return the unique Lid of the name specified\n");\r
+       fprintf(stderr, "   -G return the Guids of the name specified\n");\r
+       fprintf(stderr, "   -O return name for the Lid specified\n");\r
+       fprintf(stderr, "   -U return name for the Guid specified\n");\r
+       fprintf(stderr, "   -c get the SA's class port info\n");\r
+       fprintf(stderr, "   -s return the PortInfoRecords with isSM or "\r
+                               "isSMdisabled capability mask bit on\n");\r
+       fprintf(stderr, "   -g get multicast group info\n");\r
+       fprintf(stderr, "   -m get multicast member info\n");\r
+       fprintf(stderr, "      (if multicast group specified, list member GIDs"\r
+                               " only for group specified\n");\r
+       fprintf(stderr, "      specified, for example 'saquery -m 0xC000')\n");\r
+       fprintf(stderr, "   -x get LinkRecord info\n");\r
+       fprintf(stderr, "   --src-to-dst get a PathRecord for <src:dst>\n"\r
+                       "                where src and dst are either node "\r
+                               "names or LIDs\n");\r
+       fprintf(stderr, "   --sgid-to-dgid get a PathRecord for <sgid-dgid>\n"\r
+                       "                where sgid and dgid are addresses in "\r
+                               "IPv6 format\n");\r
+       fprintf(stderr, "   -C <ca_name> specify the SA query HCA\n");\r
+       fprintf(stderr, "   -P <ca_port> specify the SA query port\n");\r
+       fprintf(stderr, "   --smkey <val> specify SM_Key value for the query."\r
+                       " If non-numeric value \n"\r
+                       "                 (like 'x') is specified then "\r
+                       "saquery will prompt for a value\n");\r
+       fprintf(stderr, "   -t | --timeout <msec> specify the SA query "\r
+                               "response timeout (default %u msec)\n",\r
+                       DEFAULT_SA_TIMEOUT_MS);\r
+       fprintf(stderr, "   --node-name-map <node-name-map> specify a node name map\n");\r
+       fprintf(stderr, "\n   Supported query names (and aliases):\n");\r
+       for (q = query_cmds; q->name; q++)\r
+               fprintf(stderr, "      %s (%s) %s\n", q->name,\r
+                       q->alias ? q->alias : "", q->usage ? q->usage : "");\r
+       fprintf(stderr, "\n");\r
+\r
+       exit(-1);\r
+}\r
+\r
+int\r
+main(int argc, char **argv)\r
+{\r
+       int                ch = 0;\r
+       int                members = 0;\r
+       osm_bind_handle_t  bind_handle;\r
+       const struct query_cmd *q = NULL;\r
+       char              *src = NULL;\r
+       char              *dst = NULL;\r
+       char              *sgid = NULL;\r
+       char              *dgid = NULL;\r
+       ib_net16_t         query_type = 0;\r
+       ib_net16_t         src_lid;\r
+       ib_net16_t         dst_lid;\r
+       ib_api_status_t    status;\r
+\r
+       static char const str_opts[] = "pVNDLlGOUcSIsgmxdhP:C:t:";\r
+       static const struct option long_opts [] = {\r
+          {"p", 0, 0, 'p'},\r
+          {"Version", 0, 0, 'V'},\r
+          {"N", 0, 0, 'N'},\r
+          {"L", 0, 0, 'L'},\r
+          {"l", 0, 0, 'l'},\r
+          {"G", 0, 0, 'G'},\r
+          {"O", 0, 0, 'O'},\r
+          {"U", 0, 0, 'U'},\r
+          {"s", 0, 0, 's'},\r
+          {"g", 0, 0, 'g'},\r
+          {"m", 0, 0, 'm'},\r
+          {"x", 0, 0, 'x'},\r
+          {"d", 0, 0, 'd'},\r
+          {"c", 0, 0, 'c'},\r
+          {"S", 0, 0, 'S'},\r
+          {"I", 0, 0, 'I'},\r
+          {"P", 1, 0, 'P'},\r
+          {"C", 1, 0, 'C'},\r
+          {"help", 0, 0, 'h'},\r
+          {"list", 0, 0, 'D'},\r
+          {"src-to-dst", 1, 0, 1},\r
+          {"sgid-to-dgid", 1, 0, 2},\r
+          {"timeout", 1, 0, 't'},\r
+          {"node-name-map", 1, 0, 3},\r
+          {"smkey", 1, 0, 4},\r
+          { }\r
+       };\r
+\r
+       argv0 = argv[0];\r
+\r
+       while ((ch = getopt_long_only(argc, argv, str_opts, long_opts, NULL)) != -1) {\r
+               switch (ch) {\r
+               case 1:\r
+               {\r
+                       char *opt  = strdup(optarg);\r
+                       char *ch = strchr(opt, ':');\r
+                       if (!ch) {\r
+                               fprintf(stderr,\r
+                                       "ERROR: --src-to-dst <node>:<node>\n");\r
+                               usage();\r
+                       }\r
+                       *ch++ = '\0';\r
+                       if (*opt)\r
+                               src = strdup(opt);\r
+                       if (*ch)\r
+                               dst = strdup(ch);\r
+                       free(opt);\r
+                       query_type = IB_MAD_ATTR_PATH_RECORD;\r
+                       break;\r
+               }\r
+               case 2:\r
+               {\r
+                       char *opt  = strdup(optarg);\r
+                       char *tok1 = strtok(opt, "-");\r
+                       char *tok2 = strtok(NULL, "\0");\r
+\r
+                       if (tok1 && tok2) {\r
+                               sgid = strdup(tok1);\r
+                               dgid = strdup(tok2);\r
+                       } else {\r
+                               fprintf(stderr,\r
+                                       "ERROR: --sgid-to-dgid <GID>-<GID>\n");\r
+                               usage();\r
+                       }\r
+                       free(opt);\r
+                       query_type = IB_MAD_ATTR_PATH_RECORD;\r
+                       break;\r
+               }\r
+               case 3:\r
+                       node_name_map_file = strdup(optarg);\r
+                       break;\r
+               case 4:\r
+                       if (!isxdigit(*optarg) &&\r
+                           !(optarg = getpass("SM_Key: "))) {\r
+                               fprintf(stderr, "cannot get SM_Key\n");\r
+                               usage();\r
+                       }\r
+                       smkey = cl_hton64(strtoull(optarg, NULL, 0));\r
+                       break;\r
+               case 'p':\r
+                       query_type = IB_MAD_ATTR_PATH_RECORD;\r
+                       break;\r
+               case 'V':\r
+                       fprintf(stderr, "%s %s\n", argv0, get_build_version());\r
+                       exit(-1);\r
+               case 'D':\r
+                       node_print_desc = ALL_DESC;\r
+                       break;\r
+               case 'c':\r
+                       query_type = IB_MAD_ATTR_CLASS_PORT_INFO;\r
+                       break;\r
+               case 'S':\r
+                       query_type = IB_MAD_ATTR_SERVICE_RECORD;\r
+                       break;\r
+               case 'I':\r
+                       query_type = IB_MAD_ATTR_INFORM_INFO_RECORD;\r
+                       break;\r
+               case 'N':\r
+                       query_type = IB_MAD_ATTR_NODE_RECORD;\r
+                       break;\r
+               case 'L':\r
+                       node_print_desc = LID_ONLY;\r
+                       break;\r
+               case 'l':\r
+                       node_print_desc = UNIQUE_LID_ONLY;\r
+                       break;\r
+               case 'G':\r
+                       node_print_desc = GUID_ONLY;\r
+                       break;\r
+               case 'O':\r
+                       node_print_desc = NAME_OF_LID;\r
+                       break;\r
+               case 'U':\r
+                       node_print_desc = NAME_OF_GUID;\r
+                       break;\r
+               case 's':\r
+                       query_type = IB_MAD_ATTR_PORTINFO_RECORD;\r
+                       break;\r
+               case 'g':\r
+                       query_type = IB_MAD_ATTR_MCMEMBER_RECORD;\r
+                       break;\r
+               case 'm':\r
+                       query_type = IB_MAD_ATTR_MCMEMBER_RECORD;\r
+                       members = 1;\r
+                       break;\r
+               case 'x':\r
+                       query_type = IB_MAD_ATTR_LINK_RECORD;\r
+                       break;\r
+               case 'd':\r
+                       osm_debug = 1;\r
+                       break;\r
+               case 'C':\r
+                       sa_hca_name = optarg;\r
+                       break;\r
+               case 'P':\r
+                       sa_port_num = strtoul(optarg, NULL, 0);\r
+                       break;\r
+               case 't':\r
+                       sa_timeout_ms = strtoul(optarg, NULL, 0);\r
+                       break;\r
+               case 'h':\r
+               default:\r
+                       usage();\r
+               }\r
+       }\r
+       argc -= optind;\r
+       argv += optind;\r
+\r
+       if (!query_type) {\r
+               if (!argc || !(q = find_query(argv[0])))\r
+                       query_type = IB_MAD_ATTR_NODE_RECORD;\r
+               else {\r
+                       query_type = q->query_type;\r
+                       argc--;\r
+                       argv++;\r
+               }\r
+       }\r
+\r
+       if (argc) {\r
+               if (node_print_desc == NAME_OF_LID) {\r
+                       requested_lid = (ib_net16_t)strtoul(argv[0], NULL, 0);\r
+                       requested_lid_flag++;\r
+               } else if (node_print_desc == NAME_OF_GUID) {\r
+                       requested_guid = (ib_net64_t)strtoul(argv[0], NULL, 0);\r
+                       requested_guid_flag++;\r
+               } else {\r
+                       requested_name = argv[0];\r
+               }\r
+       }\r
+\r
+       if ((node_print_desc == LID_ONLY ||\r
+            node_print_desc == UNIQUE_LID_ONLY ||\r
+            node_print_desc == GUID_ONLY) &&\r
+            !requested_name) {\r
+               fprintf(stderr, "ERROR: name not specified\n");\r
+               usage();\r
+       }\r
+\r
+       if (node_print_desc == NAME_OF_LID && !requested_lid_flag) {\r
+               fprintf(stderr, "ERROR: lid not specified\n");\r
+               usage();\r
+       }\r
+\r
+       if (node_print_desc == NAME_OF_GUID && !requested_guid_flag) {\r
+               fprintf(stderr, "ERROR: guid not specified\n");\r
+               usage();\r
+       }\r
+\r
+       /* Note: lid cannot be 0; see infiniband spec 4.1.3 */\r
+       if (node_print_desc == NAME_OF_LID && !requested_lid) {\r
+               fprintf(stderr, "ERROR: lid invalid\n");\r
+               usage();\r
+       }\r
+\r
+       bind_handle = get_bind_handle();\r
+       node_name_map = open_node_name_map(node_name_map_file);\r
+\r
+       switch (query_type) {\r
+       case IB_MAD_ATTR_NODE_RECORD:\r
+               status = print_node_records(bind_handle);\r
+               break;\r
+       case IB_MAD_ATTR_PATH_RECORD:\r
+               if (src && dst) {\r
+                       src_lid = get_lid(bind_handle, src);\r
+                       dst_lid = get_lid(bind_handle, dst);\r
+                       printf("Path record for %s -> %s\n", src, dst);\r
+                       if (src_lid == 0 || dst_lid == 0) {\r
+                               status = IB_UNKNOWN_ERROR;\r
+                       } else {\r
+                               status = get_print_path_rec_lid(bind_handle, src_lid, dst_lid);\r
+                       }\r
+               } else if (sgid && dgid) {\r
+                       struct in6_addr src_addr, dst_addr;\r
+\r
+                       if (inet_pton(AF_INET6, sgid, &src_addr) <= 0) {\r
+                               fprintf(stderr, "invalid src gid: %s\n", sgid);\r
+                               exit(-1);\r
+                       }\r
+                       if (inet_pton(AF_INET6, dgid, &dst_addr) <= 0) {\r
+                               fprintf(stderr, "invalid dst gid: %s\n", dgid);\r
+                               exit(-1);\r
+                       }\r
+                       status = get_print_path_rec_gid(\r
+                               bind_handle,\r
+                               (ib_gid_t *) &src_addr.s6_addr,\r
+                               (ib_gid_t *) &dst_addr.s6_addr);\r
+               } else {\r
+                       status = print_path_records(bind_handle);\r
+               }\r
+               break;\r
+       case IB_MAD_ATTR_CLASS_PORT_INFO:\r
+               status = get_print_class_port_info(bind_handle);\r
+               break;\r
+       case IB_MAD_ATTR_PORTINFO_RECORD:\r
+               status = print_portinfo_records(bind_handle);\r
+               break;\r
+       case IB_MAD_ATTR_MCMEMBER_RECORD:\r
+               if (members)\r
+                       status = print_multicast_member_records(bind_handle);\r
+               else\r
+                       status = print_multicast_group_records(bind_handle);\r
+               break;\r
+       case IB_MAD_ATTR_SERVICE_RECORD:\r
+               status = print_service_records(bind_handle);\r
+               break;\r
+       case IB_MAD_ATTR_INFORM_INFO_RECORD:\r
+               status = print_inform_info_records(bind_handle);\r
+               break;\r
+       case IB_MAD_ATTR_LINK_RECORD:\r
+               status = print_link_records(bind_handle, argc, argv);\r
+               break;\r
+       default:\r
+               if (q && q->handler)\r
+                       status = q->handler(q, bind_handle, argc, argv);\r
+               else {\r
+                       fprintf(stderr, "Unknown query type %d\n", query_type);\r
+                       status = IB_UNKNOWN_ERROR;\r
+               }\r
+               break;\r
+       }\r
+\r
+       if (src)\r
+               free(src);\r
+       if (dst)\r
+               free(dst);\r
+       clean_up();\r
+       close_node_name_map(node_name_map);\r
+       return (status);\r
+}\r
diff --git a/branches/winverbs/tools/infiniband_diags/src/saquery/SOURCES b/branches/winverbs/tools/infiniband_diags/src/saquery/SOURCES
new file mode 100644 (file)
index 0000000..07378a6
--- /dev/null
@@ -0,0 +1,37 @@
+TARGETNAME = saquery\r
+TARGETPATH = ..\..\..\..\bin\user\obj$(BUILD_ALT_DIR)\r
+TARGETTYPE = PROGRAM\r
+\r
+UMTYPE = console\r
+UMENTRY = main\r
+\r
+USE_MSVCRT = 1\r
+USE_STL = 1\r
+USE_NATIVE_EH = 1\r
+USE_IOSTREAM = 1\r
+\r
+SOURCES = ..\saquery.c ..\ibdiag_common.c\r
+       \r
+INCLUDES = ..;..\..\include;\r
+       ..\..\..\..\ulp\opensm\user\include;\r
+       ..\..\..\..\ulp\libibmad\include;\r
+       ..\..\..\..\ulp\libibumad\include;\r
+       ..\..\..\..\inc;\r
+       ..\..\..\..\inc\user;\r
+\r
+TARGETLIBS =   \\r
+       $(SDK_LIB_PATH)\kernel32.lib    \\r
+       $(SDK_LIB_PATH)\advapi32.lib    \\r
+       $(SDK_LIB_PATH)\user32.lib      \\r
+       $(SDK_LIB_PATH)\ole32.lib       \\r
+       $(SDK_LIB_PATH)\ws2_32.lib      \\r
+!if $(FREEBUILD)\r
+       $(TARGETPATH)\*\complib.lib     \\r
+       $(TARGETPATH)\*\libibmad.lib    \\r
+       $(TARGETPATH)\*\libibumad.lib   \r
+!else\r
+       $(TARGETPATH)\*\complibd.lib    \\r
+       $(TARGETPATH)\*\libibmadd.lib   \\r
+       $(TARGETPATH)\*\libibumadd.lib  \r
+!endif\r
+\r
diff --git a/branches/winverbs/tools/infiniband_diags/src/sminfo.c b/branches/winverbs/tools/infiniband_diags/src/sminfo.c
new file mode 100644 (file)
index 0000000..18ae875
--- /dev/null
@@ -0,0 +1,210 @@
+/*\r
+ * Copyright (c) 2004-2008 Voltaire 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
+#if HAVE_CONFIG_H\r
+#  include <config.h>\r
+#endif /* HAVE_CONFIG_H */\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <stdarg.h>\r
+\r
+#if !defined(_WIN32) \r
+#include <unistd.h>\r
+#include <inttypes.h>\r
+#include <getopt.h>\r
+#else\r
+#include "..\..\..\..\etc\user\getopt.c"\r
+#endif\r
+\r
+#include <infiniband/umad.h>\r
+#include <infiniband/mad.h>\r
+\r
+#include "ibdiag_common.h"\r
+\r
+static uint8_t sminfo[1024];\r
+\r
+char *argv0 = "sminfo";\r
+\r
+static void\r
+usage(void)\r
+{\r
+       fprintf(stderr, "Usage: %s [-d(ebug) -e(rr_show) -s state -p prio -a activity -D(irect) -G(uid) -V(ersion) -C ca_name -P ca_port "\r
+                       "-t(imeout) timeout_ms] <sm_lid|sm_dr_path> [modifier]\n",\r
+                       argv0);\r
+       exit(-1);\r
+}\r
+\r
+int strdata, xdata=1, bindata;\r
+enum {\r
+       SMINFO_NOTACT,\r
+       SMINFO_DISCOVER,\r
+       SMINFO_STANDBY,\r
+       SMINFO_MASTER,\r
+\r
+       SMINFO_STATE_LAST,\r
+};\r
+\r
+char *statestr[] = {\r
+       "SMINFO_NOTACT",\r
+       "SMINFO_DISCOVER",\r
+       "SMINFO_STANDBY",\r
+       "SMINFO_MASTER",\r
+};\r
+\r
+#define STATESTR(s)    (((unsigned int)(s)) < SMINFO_STATE_LAST ? statestr[s] : "???")\r
+\r
+int __cdecl\r
+main(int argc, char **argv)\r
+{\r
+       int mgmt_classes[3] = {IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS};\r
+       int mod = 0;\r
+       ib_portid_t portid = {0};\r
+       int timeout = 0;        /* use default */\r
+       uint8_t *p;\r
+       unsigned int act = 0;\r
+       int prio = 0, state = SMINFO_STANDBY;\r
+       uint64_t guid = 0, key = 0;\r
+       extern int ibdebug;\r
+       int dest_type = IB_DEST_LID;\r
+       int udebug = 0;\r
+       char *ca = 0;\r
+       int ca_port = 0;\r
+\r
+       static char str_opts[] = "C:P:t:s:p:a:deDGVhu";\r
+       static struct option long_opts[] = {\r
+               { "C", 1, 0, 'C'},\r
+               { "P", 1, 0, 'P'},\r
+               { "debug", 0, 0, 'd'},\r
+               { "err_show", 0, 0, 'e'},\r
+               { "s", 1, 0, 's'},\r
+               { "p", 1, 0, 'p'},\r
+               { "a", 1, 0, 'a'},\r
+               { "Direct", 0, 0, 'D'},\r
+               { "Guid", 0, 0, 'G'},\r
+               { "Version", 0, 0, 'V'},\r
+               { "timeout", 1, 0, 't'},\r
+               { "help", 0, 0, 'h'},\r
+               { "usage", 0, 0, 'u'},\r
+               { 0 }\r
+       };\r
+\r
+       argv0 = argv[0];\r
+\r
+       while (1) {\r
+               int ch = getopt_long(argc, argv, str_opts, long_opts, NULL);\r
+               if ( ch == -1 )\r
+                       break;\r
+               switch(ch) {\r
+               case 'C':\r
+                       ca = optarg;\r
+                       break;\r
+               case 'P':\r
+                       ca_port = strtoul(optarg, 0, 0);\r
+                       break;\r
+               case 'd':\r
+                       ibdebug++;\r
+                       madrpc_show_errors(1);\r
+                       umad_debug(udebug);\r
+                       udebug++;\r
+                       break;\r
+               case 'e':\r
+                       madrpc_show_errors(1);\r
+                       break;\r
+               case 'D':\r
+                       dest_type = IB_DEST_DRPATH;\r
+                       break;\r
+               case 'G':\r
+                       dest_type = IB_DEST_GUID;\r
+                       break;\r
+               case 't':\r
+                       timeout = strtoul(optarg, 0, 0);\r
+                       madrpc_set_timeout(timeout);\r
+                       break;\r
+               case 'a':\r
+                       act = strtoul(optarg, 0, 0);\r
+                       break;\r
+               case 's':\r
+                       state = strtoul(optarg, 0, 0);\r
+                       break;\r
+               case 'p':\r
+                       prio = strtoul(optarg, 0, 0);\r
+                       break;\r
+               case 'V':\r
+                       fprintf(stderr, "%s %s\n", argv0, get_build_version() );\r
+                       exit(-1);\r
+               default:\r
+                       usage();\r
+                       break;\r
+               }\r
+       }\r
+       argc -= optind;\r
+       argv += optind;\r
+\r
+       if (argc > 1)\r
+               mod = atoi(argv[1]);\r
+\r
+       madrpc_init(ca, ca_port, mgmt_classes, 3);\r
+\r
+       if (argc) {\r
+               if (ib_resolve_portid_str(&portid, argv[0], dest_type, 0) < 0)\r
+                       IBERROR("can't resolve destination port %s", argv[0]);\r
+       } else {\r
+               if (ib_resolve_smlid(&portid, timeout) < 0)\r
+                       IBERROR("can't resolve sm port %s", argv[0]);\r
+       }\r
+\r
+       mad_encode_field(sminfo, IB_SMINFO_GUID_F, &guid);\r
+       mad_encode_field(sminfo, IB_SMINFO_ACT_F, &act);\r
+       mad_encode_field(sminfo, IB_SMINFO_KEY_F, &key);\r
+       mad_encode_field(sminfo, IB_SMINFO_PRIO_F, &prio);\r
+       mad_encode_field(sminfo, IB_SMINFO_STATE_F, &state);\r
+\r
+       if (mod) {\r
+               if (!(p = smp_set(sminfo, &portid, IB_ATTR_SMINFO, mod, timeout)))\r
+                       IBERROR("set");\r
+       } else\r
+               if (!(p = smp_query(sminfo, &portid, IB_ATTR_SMINFO, 0, timeout)))\r
+                       IBERROR("query");\r
+\r
+       mad_decode_field(sminfo, IB_SMINFO_GUID_F, &guid);\r
+       mad_decode_field(sminfo, IB_SMINFO_ACT_F, &act);\r
+       mad_decode_field(sminfo, IB_SMINFO_KEY_F, &key);\r
+       mad_decode_field(sminfo, IB_SMINFO_PRIO_F, &prio);\r
+       mad_decode_field(sminfo, IB_SMINFO_STATE_F, &state);\r
+\r
+       printf("sminfo: sm lid %d sm guid 0x%" PRIx64 ", activity count %u priority %d state %d %s\n",\r
+               portid.lid, guid, act, prio, state, STATESTR(state));\r
+\r
+       exit(0);\r
+}\r
diff --git a/branches/winverbs/tools/infiniband_diags/src/sminfo/SOURCES b/branches/winverbs/tools/infiniband_diags/src/sminfo/SOURCES
new file mode 100644 (file)
index 0000000..133f267
--- /dev/null
@@ -0,0 +1,30 @@
+TARGETNAME = sminfo\r
+TARGETPATH = ..\..\..\..\bin\user\obj$(BUILD_ALT_DIR)\r
+TARGETTYPE = PROGRAM\r
+\r
+UMTYPE = console\r
+UMENTRY = main\r
+\r
+USE_MSVCRT = 1\r
+USE_STL = 1\r
+USE_NATIVE_EH = 1\r
+USE_IOSTREAM = 1\r
+\r
+SOURCES = ..\sminfo.c ..\ibdiag_common.c \r
+       \r
+INCLUDES = ..;..\..\include;..\..\..\..\ulp\libibmad\include;..\..\..\..\ulp\libibumad\include;..\..\..\..\inc;..\..\..\..\inc\user;\r
+\r
+TARGETLIBS =   \\r
+       $(SDK_LIB_PATH)\kernel32.lib    \\r
+       $(SDK_LIB_PATH)\advapi32.lib    \\r
+       $(SDK_LIB_PATH)\user32.lib      \\r
+       $(SDK_LIB_PATH)\ole32.lib       \\r
+       $(SDK_LIB_PATH)\ws2_32.lib      \\r
+!if $(FREEBUILD)\r
+       $(TARGETPATH)\*\libibmad.lib    \\r
+       $(TARGETPATH)\*\libibumad.lib   \r
+!else\r
+       $(TARGETPATH)\*\libibmadd.lib   \\r
+       $(TARGETPATH)\*\libibumadd.lib  \r
+!endif\r
+\r
diff --git a/branches/winverbs/tools/infiniband_diags/src/smpdump.c b/branches/winverbs/tools/infiniband_diags/src/smpdump.c
new file mode 100644 (file)
index 0000000..2272db0
--- /dev/null
@@ -0,0 +1,354 @@
+/*\r
+ * Copyright (c) 2004-2008 Voltaire 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
+#define _GNU_SOURCE\r
+\r
+#if HAVE_CONFIG_H\r
+#  include <config.h>\r
+#endif /* HAVE_CONFIG_H */\r
+\r
+#include <inttypes.h>\r
+#include <string.h>\r
+#include <errno.h>\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <unistd.h>\r
+#include <stdarg.h>\r
+#include <sys/types.h>\r
+#include <sys/stat.h>\r
+#include <fcntl.h>\r
+#include <sys/ioctl.h>\r
+#include <unistd.h>\r
+#include <getopt.h>\r
+#include <endian.h>\r
+#include <byteswap.h>\r
+#include <sys/poll.h>\r
+#include <syslog.h>\r
+#include <netinet/in.h>\r
+\r
+#include <infiniband/common.h>\r
+#include <infiniband/mad.h>\r
+#include <infiniband/umad.h>\r
+\r
+#include <ibdiag_common.h>\r
+\r
+static const uint8_t  CLASS_SUBN_DIRECTED_ROUTE = 0x81;\r
+static const uint8_t  CLASS_SUBN_LID_ROUTE = 0x1;\r
+\r
+#define  ATTR_NODE_DESC ((uint16_t)(htons(0x10)))\r
+#define  ATTR_NODE_INFO ((uint16_t)(htons(0x11)))\r
+#define  ATTR_PORT_INFO ((uint16_t)(htons(0x15)))\r
+\r
+static int mad_agent;\r
+static int drmad_tid = 0x123;\r
+\r
+static int debug, verbose;\r
+\r
+char *argv0 = "smpdump";\r
+\r
+typedef struct {\r
+       char path[64];\r
+       int hop_cnt;\r
+} DRPath;\r
+\r
+struct drsmp {\r
+       uint8_t         base_version;\r
+       uint8_t         mgmt_class;\r
+       uint8_t         class_version;\r
+       uint8_t         method;\r
+       uint16_t        status;\r
+       uint8_t         hop_ptr;\r
+       uint8_t         hop_cnt;\r
+       uint64_t        tid;\r
+       uint16_t        attr_id;\r
+       uint16_t        resv;\r
+       uint32_t        attr_mod;\r
+       uint64_t        mkey;\r
+       uint16_t        dr_slid;\r
+       uint16_t        dr_dlid;\r
+       uint8_t         reserved[28];\r
+       uint8_t         data[64];\r
+       uint8_t         initial_path[64];\r
+       uint8_t         return_path[64];\r
+};\r
+\r
+void\r
+drsmp_get_init(void *umad, DRPath *path, int attr, int mod)\r
+{\r
+       struct drsmp *smp = (struct drsmp *)(umad_get_mad(umad));\r
+\r
+       memset(smp, 0, sizeof (*smp));\r
+\r
+       smp->base_version  = 1;\r
+       smp->mgmt_class    = CLASS_SUBN_DIRECTED_ROUTE;\r
+       smp->class_version = 1;\r
+\r
+       smp->method        = 1;\r
+       smp->attr_id       = (uint16_t)htons((uint16_t)attr);\r
+       smp->attr_mod      = htonl(mod);\r
+       smp->tid           = htonll(drmad_tid++);\r
+       smp->dr_slid       = 0xffff;\r
+       smp->dr_dlid       = 0xffff;\r
+\r
+       umad_set_addr(umad, 0xffff, 0, 0, 0);\r
+\r
+       if (path)\r
+               memcpy(smp->initial_path, path->path, path->hop_cnt+1);\r
+\r
+       smp->hop_cnt = path->hop_cnt;\r
+}\r
+\r
+void\r
+smp_get_init(void *umad, int lid, int attr, int mod)\r
+{\r
+       struct drsmp *smp = (struct drsmp *)(umad_get_mad(umad));\r
+\r
+       memset(smp, 0, sizeof (*smp));\r
+\r
+       smp->base_version  = 1;\r
+       smp->mgmt_class    = CLASS_SUBN_LID_ROUTE;\r
+       smp->class_version = 1;\r
+\r
+       smp->method        = 1;\r
+       smp->attr_id       = (uint16_t)htons((uint16_t)attr);\r
+       smp->attr_mod      = htonl(mod);\r
+       smp->tid           = htonll(drmad_tid++);\r
+\r
+       umad_set_addr(umad, lid, 0, 0xffff, 0);\r
+}\r
+\r
+void\r
+drsmp_set_init(void *umad, DRPath *path, int attr, int mod, void *data)\r
+{\r
+       struct drsmp *smp = (struct drsmp *)(umad_get_mad(umad));\r
+\r
+       memset(smp, 0, sizeof (*smp));\r
+\r
+       smp->method        = 2;         /* SET */\r
+       smp->attr_id       = (uint16_t)htons((uint16_t)attr);\r
+       smp->attr_mod      = htonl(mod);\r
+       smp->tid           = htonll(drmad_tid++);\r
+       smp->dr_slid       = 0xffff;\r
+       smp->dr_dlid       = 0xffff;\r
+\r
+       umad_set_addr(umad, 0xffff, 0, 0, 0);\r
+\r
+       if (path)\r
+               memcpy(smp->initial_path, path->path, path->hop_cnt+1);\r
+\r
+       if (data)\r
+               memcpy(smp->data, data, sizeof smp->data);\r
+\r
+       smp->hop_cnt = path->hop_cnt;\r
+}\r
+\r
+char *\r
+drmad_status_str(struct drsmp *drsmp)\r
+{\r
+       switch (drsmp->status) {\r
+       case 0:\r
+               return "success";\r
+       case ETIMEDOUT:\r
+               return "timeout";\r
+       }\r
+       return "unknown error";\r
+}\r
+\r
+int\r
+str2DRPath(char *str, DRPath *path)\r
+{\r
+       char *s;\r
+\r
+       path->hop_cnt = -1;\r
+\r
+       DEBUG("DR str: %s", str);\r
+       while (str && *str) {\r
+               if ((s = strchr(str, ',')))\r
+                       *s = 0;\r
+               path->path[++path->hop_cnt] = atoi(str);\r
+               if (!s)\r
+                       break;\r
+               str = s+1;\r
+       }\r
+\r
+#if 0\r
+       if (path->path[0] != 0 ||\r
+          (path->hop_cnt > 0 && dev_port && path->path[1] != dev_port)) {\r
+               DEBUG("hop 0 != 0 or hop 1 != dev_port");\r
+               return -1;\r
+       }\r
+#endif\r
+\r
+       return path->hop_cnt;\r
+}\r
+\r
+void\r
+usage(void)\r
+{\r
+       fprintf(stderr, "Usage: %s [-s(ring) -D(irect) -V(ersion) -C ca_name -P ca_port -t(imeout) timeout_ms] <dlid|dr_path> <attr> [mod]\n", argv0);\r
+       fprintf(stderr, "\tDR examples:\n");\r
+       fprintf(stderr, "\t\t%s -D 0,1,2,3,5 16 # NODE DESC\n", argv0);\r
+       fprintf(stderr, "\t\t%s -D 0,1,2 0x15 2 # PORT INFO, port 2\n", argv0);\r
+       fprintf(stderr, "\n\tLID routed examples:\n");\r
+       fprintf(stderr, "\t\t%s 3 0x15 2        # PORT INFO, lid 3 port 2\n", argv0);\r
+       fprintf(stderr, "\t\t%s 0xa0 0x11       # NODE INFO, lid 0xa0\n", argv0);\r
+       fprintf(stderr, "\n");\r
+       exit(-1);\r
+}\r
+\r
+int\r
+main(int argc, char *argv[])\r
+{\r
+       int dump_char = 0, timeout_ms = 1000;\r
+       int dev_port = 0, mgmt_class = CLASS_SUBN_LID_ROUTE, dlid = 0;\r
+       char *dev_name = 0;\r
+       void *umad;\r
+       struct drsmp *smp;\r
+       int i, portid, mod = 0, attr;\r
+       DRPath path;\r
+       uint8_t *desc;\r
+       int length;\r
+\r
+       static char const str_opts[] = "C:P:t:dsDVhu";\r
+       static const struct option long_opts[] = {\r
+               { "C", 1, 0, 'C'},\r
+               { "P", 1, 0, 'P'},\r
+               { "debug", 0, 0, 'd'},\r
+               { "sring", 0, 0, 's'},\r
+               { "Direct", 0, 0, 'D'},\r
+               { "timeout", 1, 0, 't'},\r
+               { "Version", 0, 0, 'V'},\r
+               { "help", 0, 0, 'h'},\r
+               { "usage", 0, 0, 'u'},\r
+               { }\r
+       };\r
+\r
+       argv0 = argv[0];\r
+\r
+       while (1) {\r
+               int ch = getopt_long(argc, argv, str_opts, long_opts, NULL);\r
+               if ( ch == -1 )\r
+                       break;\r
+               switch(ch) {\r
+               case 's':\r
+                       dump_char++;\r
+                       break;\r
+               case 'd':\r
+                       debug++;\r
+                       if (debug > 1)\r
+                               umad_debug(debug-1);\r
+                       break;\r
+               case 'D':\r
+                       mgmt_class = CLASS_SUBN_DIRECTED_ROUTE;\r
+                       break;\r
+               case 'C':\r
+                       dev_name = optarg;\r
+                       break;\r
+               case 'P':\r
+                       dev_port = atoi(optarg);\r
+                       break;\r
+               case 't':\r
+                       timeout_ms = strtoul(optarg, 0, 0);\r
+                       break;\r
+               case 'V':\r
+                       fprintf(stderr, "%s %s\n", argv0, get_build_version() );\r
+                       exit(-1);\r
+               default:\r
+                       usage();\r
+                       break;\r
+               }\r
+       }\r
+       argc -= optind;\r
+       argv += optind;\r
+\r
+       if (argc < 2)\r
+               usage();\r
+\r
+       if (mgmt_class == CLASS_SUBN_DIRECTED_ROUTE &&\r
+           str2DRPath(strdupa(argv[0]), &path) < 0)\r
+               IBPANIC("bad path str '%s'", argv[0]);\r
+\r
+       if (mgmt_class == CLASS_SUBN_LID_ROUTE)\r
+               dlid = strtoul(argv[0], 0, 0);\r
+\r
+       attr = strtoul(argv[1], 0, 0);\r
+       if (argc > 2)\r
+               mod = strtoul(argv[2], 0, 0);\r
+\r
+       if (umad_init() < 0)\r
+               IBPANIC("can't init UMAD library");\r
+\r
+       if ((portid = umad_open_port(dev_name, dev_port)) < 0)\r
+               IBPANIC("can't open UMAD port (%s:%d)", dev_name, dev_port);\r
+\r
+       if ((mad_agent = umad_register(portid, mgmt_class, 1, 0, 0)) < 0)\r
+               IBPANIC("Couldn't register agent for SMPs");\r
+\r
+       if (!(umad = umad_alloc(1, umad_size() + IB_MAD_SIZE)))\r
+               IBPANIC("can't alloc MAD");\r
+\r
+       smp = umad_get_mad(umad);\r
+\r
+       if (mgmt_class == CLASS_SUBN_DIRECTED_ROUTE)\r
+               drsmp_get_init(umad, &path, attr, mod);\r
+       else\r
+               smp_get_init(umad, dlid, attr, mod);\r
+\r
+       if (debug > 1)\r
+               xdump(stderr, "before send:\n", smp, 256);\r
+\r
+       length = IB_MAD_SIZE;\r
+       if (umad_send(portid, mad_agent, umad, length, timeout_ms, 0) < 0)\r
+               IBPANIC("send failed");\r
+\r
+       if (umad_recv(portid, umad, &length, -1) != mad_agent)\r
+               IBPANIC("recv error: %s", drmad_status_str(smp));\r
+\r
+       if (!dump_char) {\r
+               xdump(stdout, 0, smp->data, 64);\r
+               if (smp->status)\r
+                       fprintf(stdout, "SMP status: 0x%x\n", ntohs(smp->status));\r
+               return 0;\r
+       }\r
+\r
+       desc = smp->data;\r
+       for (i = 0; i < 64; ++i) {\r
+               if (!desc[i])\r
+                       break;\r
+               putchar(desc[i]);\r
+       }\r
+       putchar('\n');\r
+       if (smp->status)\r
+               fprintf(stdout, "SMP status: 0x%x\n", ntohs(smp->status));\r
+       return 0;\r
+}\r
diff --git a/branches/winverbs/tools/infiniband_diags/src/smpquery.c b/branches/winverbs/tools/infiniband_diags/src/smpquery.c
new file mode 100644 (file)
index 0000000..2e8d369
--- /dev/null
@@ -0,0 +1,538 @@
+/*\r
+ * Copyright (c) 2004-2008 Voltaire 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
+#if HAVE_CONFIG_H\r
+#  include <config.h>\r
+#endif /* HAVE_CONFIG_H */\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <unistd.h>\r
+#include <stdarg.h>\r
+#include <time.h>\r
+#include <string.h>\r
+#include <getopt.h>\r
+#include <netinet/in.h>\r
+\r
+#define __STDC_FORMAT_MACROS\r
+#include <inttypes.h>\r
+\r
+#include <infiniband/common.h>\r
+#include <infiniband/umad.h>\r
+#include <infiniband/mad.h>\r
+#include <infiniband/complib/cl_nodenamemap.h>\r
+\r
+#include "ibdiag_common.h"\r
+\r
+#undef DEBUG\r
+#define        DEBUG   if (verbose>1) IBWARN\r
+\r
+static int dest_type = IB_DEST_LID;\r
+static int verbose;\r
+\r
+typedef char *(op_fn_t)(ib_portid_t *dest, char **argv, int argc);\r
+\r
+typedef struct match_rec {\r
+       char *name;\r
+       op_fn_t *fn;\r
+       unsigned opt_portnum;\r
+} match_rec_t;\r
+\r
+static op_fn_t node_desc, node_info, port_info, switch_info, pkey_table,\r
+       sl2vl_table, vlarb_table, guid_info;\r
+\r
+static const match_rec_t match_tbl[] = {\r
+       { "nodeinfo", node_info },\r
+       { "nodedesc", node_desc },\r
+       { "portinfo", port_info, 1 },\r
+       { "switchinfo", switch_info },\r
+       { "pkeys", pkey_table, 1 },\r
+       { "sl2vl", sl2vl_table, 1 },\r
+       { "vlarb", vlarb_table, 1 },\r
+       { "guids", guid_info },\r
+       {0}\r
+};\r
+\r
+char *argv0 = "smpquery";\r
+static char *node_name_map_file = NULL;\r
+static nn_map_t *node_name_map = NULL;\r
+\r
+/*******************************************/\r
+static char *\r
+node_desc(ib_portid_t *dest, char **argv, int argc)\r
+{\r
+       int       node_type, l;\r
+       uint64_t  node_guid;\r
+       char      nd[IB_SMP_DATA_SIZE];\r
+       uint8_t   data[IB_SMP_DATA_SIZE];\r
+       char      dots[128];\r
+       char     *nodename = NULL;\r
+\r
+       if (!smp_query(data, dest, IB_ATTR_NODE_INFO, 0, 0))\r
+               return "node info query failed";\r
+\r
+       mad_decode_field(data, IB_NODE_TYPE_F, &node_type);\r
+       mad_decode_field(data, IB_NODE_GUID_F, &node_guid);\r
+\r
+       if (!smp_query(nd, dest, IB_ATTR_NODE_DESC, 0, 0))\r
+               return "node desc query failed";\r
+\r
+       nodename = remap_node_name(node_name_map, node_guid, nd);\r
+\r
+       l = strlen(nodename);\r
+       if (l < 32) {\r
+               memset(dots, '.', 32 - l);\r
+               dots[32 - l] = '\0';\r
+       } else {\r
+               dots[0] = '.';\r
+               dots[1] = '\0';\r
+       }\r
+\r
+       printf("Node Description:%s%s\n", dots, nodename);\r
+       free(nodename);\r
+       return 0;\r
+}\r
+\r
+static char *\r
+node_info(ib_portid_t *dest, char **argv, int argc)\r
+{\r
+       char buf[2048];\r
+       char data[IB_SMP_DATA_SIZE];\r
+\r
+       if (!smp_query(data, dest, IB_ATTR_NODE_INFO, 0, 0))\r
+               return "node info query failed";\r
+\r
+       mad_dump_nodeinfo(buf, sizeof buf, data, sizeof data);\r
+\r
+       printf("# Node info: %s\n%s", portid2str(dest), buf);\r
+       return 0;\r
+}\r
+\r
+static char *\r
+port_info(ib_portid_t *dest, char **argv, int argc)\r
+{\r
+       char buf[2048];\r
+       char data[IB_SMP_DATA_SIZE];\r
+       int portnum = 0;\r
+\r
+       if (argc > 0)\r
+               portnum = strtol(argv[0], 0, 0);\r
+\r
+       if (!smp_query(data, dest, IB_ATTR_PORT_INFO, portnum, 0))\r
+               return "port info query failed";\r
+\r
+       mad_dump_portinfo(buf, sizeof buf, data, sizeof data);\r
+\r
+       printf("# Port info: %s port %d\n%s", portid2str(dest), portnum, buf);\r
+       return 0;\r
+}\r
+\r
+static char *\r
+switch_info(ib_portid_t *dest, char **argv, int argc)\r
+{\r
+       char buf[2048];\r
+       char data[IB_SMP_DATA_SIZE];\r
+\r
+       if (!smp_query(data, dest, IB_ATTR_SWITCH_INFO, 0, 0))\r
+               return "switch info query failed";\r
+\r
+       mad_dump_switchinfo(buf, sizeof buf, data, sizeof data);\r
+\r
+       printf("# Switch info: %s\n%s", portid2str(dest), buf);\r
+       return 0;\r
+}\r
+\r
+static char *\r
+pkey_table(ib_portid_t *dest, char **argv, int argc)\r
+{\r
+       uint8_t data[IB_SMP_DATA_SIZE];\r
+       uint32_t i, j, k;\r
+       uint16_t *p;\r
+       uint mod;\r
+       int n, t, phy_ports;\r
+       int portnum = 0;\r
+\r
+       if (argc > 0)\r
+               portnum = strtol(argv[0], 0, 0);\r
+\r
+       /* Get the partition capacity */\r
+       if (!smp_query(data, dest, IB_ATTR_NODE_INFO, 0, 0))\r
+               return "node info query failed";\r
+\r
+       mad_decode_field(data, IB_NODE_TYPE_F, &t);\r
+       mad_decode_field(data, IB_NODE_NPORTS_F, &phy_ports);\r
+       if (portnum > phy_ports)\r
+               return "invalid port number";\r
+\r
+       if ((t == IB_NODE_SWITCH) && (portnum != 0)) {\r
+               if (!smp_query(data, dest, IB_ATTR_SWITCH_INFO, 0, 0))\r
+                       return "switch info failed";\r
+               mad_decode_field(data, IB_SW_PARTITION_ENFORCE_CAP_F, &n);\r
+       } else\r
+               mad_decode_field(data, IB_NODE_PARTITION_CAP_F, &n);\r
+\r
+       for (i = 0; i < (n + 31) / 32; i++) {\r
+               mod =  i | (portnum << 16);\r
+               if (!smp_query(data, dest, IB_ATTR_PKEY_TBL, mod, 0))\r
+                       return "pkey table query failed";\r
+               if (i + 1 == (n + 31) / 32)\r
+                       k = ((n + 7 - i * 32) / 8) * 8;\r
+               else\r
+                       k = 32;\r
+               p = (uint16_t *) data;\r
+               for (j = 0; j < k; j += 8, p += 8) {\r
+                       printf("%4u: 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x\n",\r
+                               (i * 32) + j,\r
+                               ntohs(p[0]), ntohs(p[1]),\r
+                               ntohs(p[2]), ntohs(p[3]),\r
+                               ntohs(p[4]), ntohs(p[5]),\r
+                               ntohs(p[6]), ntohs(p[7]));\r
+               }\r
+       }\r
+       printf("%d pkeys capacity for this port\n", n);\r
+\r
+       return 0;\r
+}\r
+\r
+static char *sl2vl_dump_table_entry(ib_portid_t *dest, int in, int out)\r
+{\r
+       char buf[2048];\r
+       char data[IB_SMP_DATA_SIZE];\r
+       int portnum = (in << 8) | out;\r
+\r
+       if (!smp_query(data, dest, IB_ATTR_SLVL_TABLE, portnum, 0))\r
+               return "slvl query failed";\r
+\r
+       mad_dump_sltovl(buf, sizeof buf, data, sizeof data);\r
+       printf("ports: in %2d, out %2d: ", in, out);\r
+       printf("%s", buf);\r
+       return 0;\r
+}\r
+\r
+static char *\r
+sl2vl_table(ib_portid_t *dest, char **argv, int argc)\r
+{\r
+       uint8_t data[IB_SMP_DATA_SIZE];\r
+       int type, num_ports, portnum = 0;\r
+       int i;\r
+       char *ret;\r
+\r
+       if (argc > 0)\r
+               portnum = strtol(argv[0], 0, 0);\r
+\r
+       if (!smp_query(data, dest, IB_ATTR_NODE_INFO, 0, 0))\r
+               return "node info query failed";\r
+\r
+       mad_decode_field(data, IB_NODE_TYPE_F, &type);\r
+       mad_decode_field(data, IB_NODE_NPORTS_F, &num_ports);\r
+       if (portnum > num_ports)\r
+               return "invalid port number";\r
+\r
+       printf("# SL2VL table: %s\n", portid2str(dest));\r
+       printf("#                 SL: |");\r
+       for (i = 0 ; i < 16 ; i++)\r
+               printf("%2d|", i);\r
+       printf("\n");\r
+\r
+       if (type != IB_NODE_SWITCH)\r
+               return sl2vl_dump_table_entry(dest, 0, 0);\r
+\r
+       for (i = 0 ; i <= num_ports ; i++) {\r
+               ret = sl2vl_dump_table_entry(dest, i, portnum);\r
+               if (ret)\r
+                       return ret;\r
+       }\r
+       return 0;\r
+}\r
+\r
+static char *vlarb_dump_table_entry(ib_portid_t *dest, int portnum, int offset, unsigned cap)\r
+{\r
+       char buf[2048];\r
+       char data[IB_SMP_DATA_SIZE];\r
+\r
+       if (!smp_query(data, dest, IB_ATTR_VL_ARBITRATION,\r
+                       (offset << 16) | portnum, 0))\r
+               return "vl arb query failed";\r
+       mad_dump_vlarbitration(buf, sizeof(buf), data, cap * 2);\r
+       printf("%s", buf);\r
+       return 0;\r
+}\r
+\r
+static char *vlarb_dump_table(ib_portid_t *dest, int portnum,\r
+       char *name, int offset, int cap)\r
+{\r
+       char *ret;\r
+\r
+       printf("# %s priority VL Arbitration Table:", name);\r
+       ret = vlarb_dump_table_entry(dest, portnum, offset,\r
+                                    cap < 32 ? cap : 32);\r
+       if (!ret && cap > 32)\r
+               ret = vlarb_dump_table_entry(dest, portnum, offset + 1,\r
+                                            cap - 32);\r
+       return ret;\r
+}\r
+\r
+static char *\r
+vlarb_table(ib_portid_t *dest, char **argv, int argc)\r
+{\r
+       uint8_t data[IB_SMP_DATA_SIZE];\r
+       int portnum = 0;\r
+       int type, enhsp0, lowcap, highcap;\r
+       char *ret = 0;\r
+\r
+       if (argc > 0)\r
+               portnum = strtol(argv[0], 0, 0);\r
+\r
+       /* port number of 0 could mean SP0 or port MAD arrives on */\r
+       if (portnum == 0) {\r
+               if (!smp_query(data, dest, IB_ATTR_NODE_INFO, 0, 0))\r
+                       return "node info query failed";\r
+\r
+               mad_decode_field(data, IB_NODE_TYPE_F, &type);\r
+               if (type == IB_NODE_SWITCH) {\r
+                       if (!smp_query(data, dest, IB_ATTR_SWITCH_INFO, 0, 0))\r
+                               return "switch info query failed";\r
+                       mad_decode_field(data, IB_SW_ENHANCED_PORT0_F, &enhsp0);\r
+                       if (!enhsp0) {\r
+                               printf("# No VLArbitration tables (BSP0): %s port %d\n",\r
+                                       portid2str(dest), 0);\r
+                               return 0;\r
+                       }\r
+               }\r
+       }\r
+\r
+       if (!smp_query(data, dest, IB_ATTR_PORT_INFO, portnum, 0))\r
+               return "port info query failed";\r
+\r
+       mad_decode_field(data, IB_PORT_VL_ARBITRATION_LOW_CAP_F, &lowcap);\r
+       mad_decode_field(data, IB_PORT_VL_ARBITRATION_HIGH_CAP_F,&highcap);\r
+\r
+       printf("# VLArbitration tables: %s port %d LowCap %d HighCap %d\n",\r
+                       portid2str(dest), portnum, lowcap, highcap);\r
+\r
+       if (lowcap > 0)\r
+               ret = vlarb_dump_table(dest, portnum, "Low", 1, lowcap);\r
+\r
+       if (!ret && highcap > 0)\r
+               ret = vlarb_dump_table(dest, portnum, "High", 3, highcap);\r
+\r
+       return ret;\r
+}\r
+\r
+static char *\r
+guid_info(ib_portid_t *dest, char **argv, int argc)\r
+{\r
+       uint8_t data[IB_SMP_DATA_SIZE];\r
+       uint32_t i, j, k;\r
+       uint64_t *p;\r
+       uint mod;\r
+       int n;\r
+\r
+       /* Get the guid capacity */\r
+       if (!smp_query(data, dest, IB_ATTR_PORT_INFO, 0, 0))\r
+               return "port info failed";\r
+       mad_decode_field(data, IB_PORT_GUID_CAP_F, &n);\r
+\r
+       for (i = 0; i < (n + 7) / 8; i++) {\r
+               mod =  i;\r
+               if (!smp_query(data, dest, IB_ATTR_GUID_INFO, mod, 0))\r
+                       return "guid info query failed";\r
+               if (i + 1 == (n + 7) / 8)\r
+                       k = ((n + 1 - i * 8) / 2) * 2;\r
+               else\r
+                       k = 8;\r
+               p = (uint64_t *) data;\r
+               for (j = 0; j < k; j += 2, p += 2) {\r
+                       printf("%4u: 0x%016"PRIx64" 0x%016"PRIx64"\n",\r
+                               (i * 8) + j,\r
+                               ntohll(p[0]), ntohll(p[1]));\r
+               }\r
+       }\r
+       printf("%d guids capacity for this port\n", n);\r
+\r
+       return 0;\r
+}\r
+\r
+static op_fn_t *\r
+match_op(char *name)\r
+{\r
+       const match_rec_t *r;\r
+       for (r = match_tbl; r->name; r++)\r
+               if (!strcmp(r->name, name))\r
+                       return r->fn;\r
+       return 0;\r
+}\r
+\r
+static void\r
+usage(void)\r
+{\r
+       char *basename;\r
+       const match_rec_t *r;\r
+\r
+       if (!(basename = strrchr(argv0, '/')))\r
+               basename = argv0;\r
+       else\r
+               basename++;\r
+\r
+       fprintf(stderr, "Usage: %s [-d(ebug) -e(rr_show) -v(erbose) -D(irect) -G(uid) -s smlid -V(ersion) -C ca_name -P ca_port "\r
+                       "-t(imeout) timeout_ms --node-name-map node-name-map] <op> <dest dr_path|lid|guid> [op params]\n",\r
+                       basename);\r
+       fprintf(stderr, "\tsupported ops:\n");\r
+       for (r = match_tbl ; r->name ; r++) {\r
+               fprintf(stderr, "\t\t%s <addr>%s\n", r->name,\r
+                               r->opt_portnum ? " [<portnum>]" : "");\r
+       }\r
+       fprintf(stderr, "\n\texamples:\n");\r
+       fprintf(stderr, "\t\t%s portinfo 3 1\t\t\t\t# portinfo by lid, with port modifier\n", basename);\r
+       fprintf(stderr, "\t\t%s -G switchinfo 0x2C9000100D051 1\t# switchinfo by guid\n", basename);\r
+       fprintf(stderr, "\t\t%s -D nodeinfo 0\t\t\t\t# nodeinfo by direct route\n", basename);\r
+       fprintf(stderr, "\t\t%s -c nodeinfo 6 0,12\t\t\t# nodeinfo by combined route\n", basename);\r
+       exit(-1);\r
+}\r
+\r
+int\r
+main(int argc, char **argv)\r
+{\r
+       int mgmt_classes[3] = {IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS};\r
+       ib_portid_t portid = {0};\r
+       ib_portid_t *sm_id = 0, sm_portid = {0};\r
+       extern int ibdebug;\r
+       int timeout = 0, udebug = 0;\r
+       char *ca = 0;\r
+       int ca_port = 0;\r
+       char *err;\r
+       op_fn_t *fn;\r
+\r
+       static char const str_opts[] = "C:P:t:s:devDcGVhu";\r
+       static const struct option long_opts[] = {\r
+               { "C", 1, 0, 'C'},\r
+               { "P", 1, 0, 'P'},\r
+               { "debug", 0, 0, 'd'},\r
+               { "err_show", 0, 0, 'e'},\r
+               { "verbose", 0, 0, 'v'},\r
+               { "Direct", 0, 0, 'D'},\r
+               { "combined", 0, 0, 'c'},\r
+               { "Guid", 0, 0, 'G'},\r
+               { "smlid", 1, 0, 's'},\r
+               { "timeout", 1, 0, 't'},\r
+               { "node-name-map", 1, 0, 1},\r
+               { "Version", 0, 0, 'V'},\r
+               { "help", 0, 0, 'h'},\r
+               { "usage", 0, 0, 'u'},\r
+               { }\r
+       };\r
+\r
+       argv0 = argv[0];\r
+\r
+       while (1) {\r
+               int ch = getopt_long(argc, argv, str_opts, long_opts, NULL);\r
+               if ( ch == -1 )\r
+                       break;\r
+               switch(ch) {\r
+               case 1:\r
+                       node_name_map_file = strdup(optarg);\r
+                       break;\r
+               case 'd':\r
+                       ibdebug++;\r
+                       madrpc_show_errors(1);\r
+                       umad_debug(udebug);\r
+                       udebug++;\r
+                       break;\r
+               case 'e':\r
+                       madrpc_show_errors(1);\r
+                       break;\r
+               case 'D':\r
+                       dest_type = IB_DEST_DRPATH;\r
+                       break;\r
+               case 'c':\r
+                       dest_type = IB_DEST_DRSLID;\r
+                       break;\r
+               case 'G':\r
+                       dest_type = IB_DEST_GUID;\r
+                       break;\r
+               case 'C':\r
+                       ca = optarg;\r
+                       break;\r
+               case 'P':\r
+                       ca_port = strtoul(optarg, 0, 0);\r
+                       break;\r
+               case 's':\r
+                       if (ib_resolve_portid_str(&sm_portid, optarg, IB_DEST_LID, 0) < 0)\r
+                               IBERROR("can't resolve SM destination port %s", optarg);\r
+                       sm_id = &sm_portid;\r
+                       break;\r
+               case 't':\r
+                       timeout = strtoul(optarg, 0, 0);\r
+                       madrpc_set_timeout(timeout);\r
+                       break;\r
+               case 'v':\r
+                       verbose++;\r
+                       break;\r
+               case 'V':\r
+                       fprintf(stderr, "%s %s\n", argv0, get_build_version() );\r
+                       exit(-1);\r
+               default:\r
+                       usage();\r
+                       break;\r
+               }\r
+       }\r
+       argc -= optind;\r
+       argv += optind;\r
+\r
+       if (argc < 2)\r
+               usage();\r
+\r
+       if (!(fn = match_op(argv[0])))\r
+               IBERROR("operation '%s' not supported", argv[0]);\r
+\r
+       madrpc_init(ca, ca_port, mgmt_classes, 3);\r
+       node_name_map = open_node_name_map(node_name_map_file);\r
+\r
+       if (dest_type != IB_DEST_DRSLID) {\r
+               if (ib_resolve_portid_str(&portid, argv[1], dest_type, sm_id) < 0)\r
+                       IBERROR("can't resolve destination port %s", argv[1]);\r
+               if ((err = fn(&portid, argv+2, argc-2)))\r
+                       IBERROR("operation %s: %s", argv[0], err);\r
+       } else {\r
+               char concat[64];\r
+\r
+               memset(concat, 0, 64);\r
+               snprintf(concat, sizeof(concat), "%s %s", argv[1], argv[2]);\r
+               if (ib_resolve_portid_str(&portid, concat, dest_type, sm_id) < 0)\r
+                       IBERROR("can't resolve destination port %s", concat);\r
+               if ((err = fn(&portid, argv+3, argc-3)))\r
+                       IBERROR("operation %s: %s", argv[0], err);\r
+       }\r
+       close_node_name_map(node_name_map);\r
+       exit(0);\r
+}\r
diff --git a/branches/winverbs/tools/infiniband_diags/src/vendstat.c b/branches/winverbs/tools/infiniband_diags/src/vendstat.c
new file mode 100644 (file)
index 0000000..4bbd704
--- /dev/null
@@ -0,0 +1,313 @@
+/*\r
+ * Copyright (c) 2004-2008 Voltaire 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
+#if HAVE_CONFIG_H\r
+#  include <config.h>\r
+#endif /* HAVE_CONFIG_H */\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#if defined(_WIN32) \r
+#include <windows.h>\r
+#include <winsock2.h>\r
+#include "..\..\..\..\etc\user\getopt.c"\r
+#else\r
+#include <unistd.h>\r
+#include <stdarg.h>\r
+#include <getopt.h>\r
+#include <netinet/in.h>\r
+#endif\r
+\r
+#include <infiniband/umad.h>\r
+#include <infiniband/mad.h>\r
+\r
+#include "ibdiag_common.h"\r
+\r
+#define IS3_DEVICE_ID                  47396\r
+\r
+#define IB_MLX_VENDOR_CLASS            10\r
+/* Vendor specific Attribute IDs */\r
+#define IB_MLX_IS3_GENERAL_INFO                0x17\r
+#define IB_MLX_IS3_CONFIG_SPACE_ACCESS 0x50\r
+/* Config space addresses */\r
+#define IB_MLX_IS3_PORT_XMIT_WAIT      0x10013C\r
+\r
+char *argv0 = "vendstat";\r
+\r
+typedef struct {\r
+       uint16_t hw_revision;\r
+       uint16_t device_id;\r
+       uint8_t  reserved[24];\r
+       uint32_t uptime;\r
+} is3_hw_info_t;\r
+\r
+typedef struct {\r
+       uint8_t resv1;\r
+       uint8_t major;\r
+       uint8_t minor;\r
+       uint8_t sub_minor;\r
+       uint32_t build_id;\r
+       uint8_t month;\r
+       uint8_t day;\r
+       uint16_t year;\r
+       uint16_t resv2;\r
+       uint16_t hour;\r
+       uint8_t psid[16];\r
+       uint32_t ini_file_version;\r
+} is3_fw_info_t;\r
+\r
+typedef struct {\r
+       uint8_t resv1;\r
+       uint8_t major;\r
+       uint8_t minor;\r
+       uint8_t sub_minor;\r
+       uint8_t resv2[28];\r
+} is3_sw_info_t;\r
+\r
+typedef struct {\r
+       uint8_t       reserved[8];\r
+       is3_hw_info_t hw_info;\r
+       is3_fw_info_t fw_info;\r
+       is3_sw_info_t sw_info;\r
+} is3_general_info_t;\r
+\r
+typedef struct {\r
+       uint32_t address;\r
+       uint32_t data;\r
+       uint32_t mask;\r
+} is3_record_t;\r
+\r
+typedef struct {\r
+       uint8_t      reserved[8];\r
+       is3_record_t record[18];\r
+} is3_config_space_t;\r
+\r
+static void\r
+usage(void)\r
+{\r
+       char *basename;\r
+\r
+       if (!(basename = strrchr(argv0, '/')))\r
+               basename = argv0;\r
+       else\r
+               basename++;\r
+\r
+       fprintf(stderr, "Usage: %s [-d(ebug) -N -w -G(uid) -C ca_name -P ca_port "\r
+                       "-t(imeout) timeout_ms -V(ersion) -h(elp)] <lid|guid>\n",\r
+                       basename);\r
+       fprintf(stderr, "\tExamples:\n");\r
+       fprintf(stderr, "\t\t%s -N 6\t\t# read IS3 general information\n", basename);\r
+       fprintf(stderr, "\t\t%s -w 6\t\t# read IS3 port xmit wait counters\n", basename);\r
+       exit(-1);\r
+}\r
+\r
+int __cdecl\r
+main(int argc, char **argv)\r
+{\r
+       int mgmt_classes[4] = {IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS, IB_MLX_VENDOR_CLASS};\r
+       ib_portid_t *sm_id = 0, sm_portid = {0};\r
+       ib_portid_t portid = {0};\r
+       extern int ibdebug;\r
+       int dest_type = IB_DEST_LID;\r
+       int timeout = 0;        /* use default */\r
+       int port = 0;\r
+       char buf[1024];\r
+       int udebug = 0;\r
+       char *ca = 0;\r
+       int ca_port = 0;\r
+       ib_vendor_call_t call;\r
+       is3_general_info_t *gi;\r
+       is3_config_space_t *cs;\r
+       int general_info = 0;\r
+       int xmit_wait = 0;\r
+       int i;\r
+\r
+       static char str_opts[] = "C:P:s:t:dNwGVhu";\r
+       static struct option long_opts[] = {\r
+               { "C", 1, 0, 'C'},\r
+               { "P", 1, 0, 'P'},\r
+               { "N", 1, 0, 'N'},\r
+               { "w", 1, 0, 'w'},\r
+               { "debug", 0, 0, 'd'},\r
+               { "Guid", 0, 0, 'G'},\r
+               { "sm_portid", 1, 0, 's'},\r
+               { "timeout", 1, 0, 't'},\r
+               { "Version", 0, 0, 'V'},\r
+               { "help", 0, 0, 'h'},\r
+               { "usage", 0, 0, 'u'},\r
+               { 0 }\r
+       };\r
+\r
+       argv0 = argv[0];\r
+\r
+       while (1) {\r
+               int ch = getopt_long(argc, argv, str_opts, long_opts, NULL);\r
+               if ( ch == -1 )\r
+                       break;\r
+               switch(ch) {\r
+               case 'C':\r
+                       ca = optarg;\r
+                       break;\r
+               case 'P':\r
+                       ca_port = strtoul(optarg, 0, 0);\r
+                       break;\r
+               case 'N':\r
+                       general_info = 1;\r
+                       break;\r
+               case 'w':\r
+                       xmit_wait = 1;\r
+                       break;\r
+               case 'd':\r
+                       ibdebug++;\r
+                       madrpc_show_errors(1);\r
+                       umad_debug(udebug);\r
+                       udebug++;\r
+                       break;\r
+               case 'G':\r
+                       dest_type = IB_DEST_GUID;\r
+                       break;\r
+               case 's':\r
+                       if (ib_resolve_portid_str(&sm_portid, optarg, IB_DEST_LID, 0) < 0)\r
+                               IBERROR("can't resolve SM destination port %s", optarg);\r
+                       sm_id = &sm_portid;\r
+                       break;\r
+               case 't':\r
+                       timeout = strtoul(optarg, 0, 0);\r
+                       madrpc_set_timeout(timeout);\r
+                       break;\r
+               case 'V':\r
+                       fprintf(stderr, "%s %s\n", argv0, get_build_version() );\r
+                       exit(-1);\r
+               default:\r
+                       usage();\r
+                       break;\r
+               }\r
+       }\r
+       argc -= optind;\r
+       argv += optind;\r
+\r
+       if (argc > 1)\r
+               port = strtoul(argv[1], 0, 0);\r
+\r
+       madrpc_init(ca, ca_port, mgmt_classes, 4);\r
+\r
+       if (argc) {\r
+               if (ib_resolve_portid_str(&portid, argv[0], dest_type, sm_id) < 0)\r
+                       IBERROR("can't resolve destination port %s", argv[0]);\r
+       } else {\r
+               if (ib_resolve_self(&portid, &port, 0) < 0)\r
+                       IBERROR("can't resolve self port %s", argv[0]);\r
+       }\r
+\r
+       /* Only General Info and Port Xmit Wait Counters */\r
+       /* queries are currently supported */\r
+       if (!general_info && !xmit_wait)\r
+               IBERROR("at least one of -N and -w must be specified");\r
+\r
+       /* These are Mellanox specific vendor MADs */\r
+       /* but vendors change the VendorId so how know for sure ? */\r
+       /* Would need a list of these and it might not be complete */\r
+       /* so for right now, punt on this */\r
+\r
+       memset(&call, 0, sizeof(call));\r
+       call.mgmt_class = IB_MLX_VENDOR_CLASS;\r
+       call.method = IB_MAD_METHOD_GET;\r
+       call.timeout = timeout;\r
+\r
+       memset(&buf, 0, sizeof(buf));\r
+       /* vendor ClassPortInfo is required attribute if class supported */\r
+       call.attrid = CLASS_PORT_INFO;\r
+       if (!ib_vendor_call(&buf, &portid, &call))\r
+               IBERROR("classportinfo query");\r
+\r
+       memset(&buf, 0, sizeof(buf));\r
+       call.attrid = IB_MLX_IS3_GENERAL_INFO;\r
+       if (!ib_vendor_call(&buf, &portid, &call))\r
+               IBERROR("vendstat");\r
+       gi = (is3_general_info_t *)&buf;\r
+\r
+       if (general_info) {\r
+               /* dump IS3 general info here */\r
+               printf("hw_dev_rev:  0x%04x\n", ntohs(gi->hw_info.hw_revision));\r
+               printf("hw_dev_id:   0x%04x\n", ntohs(gi->hw_info.device_id));\r
+               printf("hw_uptime:   0x%08x\n", ntohl(gi->hw_info.uptime));\r
+               printf("fw_version:  %02d.%02d.%02d\n",\r
+                      gi->fw_info.major, gi->fw_info.minor, gi->fw_info.sub_minor);\r
+               printf("fw_build_id: 0x%04x\n", ntohl(gi->fw_info.build_id));\r
+               printf("fw_date:     %02d/%02d/%04x\n",\r
+                      gi->fw_info.month, gi->fw_info.day, ntohs(gi->fw_info.year));\r
+               printf("fw_psid:     '%s'\n", gi->fw_info.psid);\r
+               printf("fw_ini_ver:  %d\n", ntohl(gi->fw_info.ini_file_version));\r
+               printf("sw_version:  %02d.%02d.%02d\n",\r
+                      gi->sw_info.major, gi->sw_info.minor, gi->sw_info.sub_minor);\r
+       }\r
+\r
+       if (xmit_wait) {\r
+               if (ntohs(gi->hw_info.device_id) != IS3_DEVICE_ID)\r
+                       IBERROR("Unsupported device ID 0x%x", ntohs(gi->hw_info.device_id));\r
+\r
+               memset(&buf, 0, sizeof(buf));\r
+               call.attrid = IB_MLX_IS3_CONFIG_SPACE_ACCESS;\r
+               /* Limit of 18 accesses per MAD ? */\r
+               call.mod = 2 << 22 | 16 << 16; /* 16 records */\r
+               /* Set record addresses for each port */\r
+               cs = (is3_config_space_t *)&buf;\r
+               for (i = 0; i < 16; i++)\r
+                       cs->record[i].address = htonl(IB_MLX_IS3_PORT_XMIT_WAIT + ((i + 1) << 12));\r
+               if (!ib_vendor_call(&buf, &portid, &call))\r
+                       IBERROR("vendstat");\r
+\r
+               for (i = 0; i < 16; i++)\r
+                       if (cs->record[i].data) /* PortXmitWait is 32 bit counter */\r
+                               printf("Port %d: PortXmitWait 0x%x\n", i + 4, ntohl(cs->record[i].data)); /* port 4 is first port */\r
+\r
+               /* Last 8 ports is another query */\r
+               memset(&buf, 0, sizeof(buf));\r
+               call.attrid = IB_MLX_IS3_CONFIG_SPACE_ACCESS;\r
+                call.mod = 2 << 22 | 8 << 16; /* 8 records */\r
+               /* Set record addresses for each port */\r
+               cs = (is3_config_space_t *)&buf;\r
+               for (i = 0; i < 8; i++)\r
+                       cs->record[i].address = htonl(IB_MLX_IS3_PORT_XMIT_WAIT + ((i + 17) << 12));\r
+               if (!ib_vendor_call(&buf, &portid, &call))\r
+                       IBERROR("vendstat");\r
+\r
+               for (i = 0; i < 8; i++)\r
+                       if (cs->record[i].data) /* PortXmitWait is 32 bit counter */\r
+                               printf("Port %d: PortXmitWait 0x%x\n",\r
+                                      i < 4 ? i + 21 : i - 3,\r
+                                      ntohl(cs->record[i].data));\r
+       }\r
+\r
+       exit(0);\r
+}\r
diff --git a/branches/winverbs/tools/infiniband_diags/src/vendstat/SOURCES b/branches/winverbs/tools/infiniband_diags/src/vendstat/SOURCES
new file mode 100644 (file)
index 0000000..c61861f
--- /dev/null
@@ -0,0 +1,32 @@
+TARGETNAME = vendstat\r
+TARGETPATH = ..\..\..\..\bin\user\obj$(BUILD_ALT_DIR)\r
+TARGETTYPE = PROGRAM\r
+\r
+UMTYPE = console\r
+UMENTRY = main\r
+\r
+USE_MSVCRT = 1\r
+USE_STL = 1\r
+USE_NATIVE_EH = 1\r
+USE_IOSTREAM = 1\r
+\r
+SOURCES = ..\vendstat.c ..\ibdiag_common.c\r
+       \r
+INCLUDES = ..;..\..\include;..\..\..\..\ulp\libibmad\include;..\..\..\..\ulp\libibumad\include;..\..\..\..\inc;..\..\..\..\inc\user;\r
+\r
+TARGETLIBS =   \\r
+       $(SDK_LIB_PATH)\kernel32.lib    \\r
+       $(SDK_LIB_PATH)\advapi32.lib    \\r
+       $(SDK_LIB_PATH)\user32.lib      \\r
+       $(SDK_LIB_PATH)\ole32.lib       \\r
+       $(SDK_LIB_PATH)\ws2_32.lib      \\r
+!if $(FREEBUILD)\r
+       $(TARGETPATH)\*\complib.lib     \\r
+       $(TARGETPATH)\*\libibmad.lib    \\r
+       $(TARGETPATH)\*\libibumad.lib   \r
+!else\r
+       $(TARGETPATH)\*\complibd.lib    \\r
+       $(TARGETPATH)\*\libibmadd.lib   \\r
+       $(TARGETPATH)\*\libibumadd.lib  \r
+!endif\r
+\r