--- /dev/null
+DIRS = \\r
+ src
\ No newline at end of file
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+DIRS = \\r
+ sminfo \\r
+ ibstat \\r
+ perfquery \\r
+ vendstat \\r
+ ibaddr\r
+ \r
+ \r
+ \r
+ \r
+ \r
+ \r
+
\ No newline at end of file
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+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
--- /dev/null
+/*\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
--- /dev/null
+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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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(¬ice, 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, ¬ice));\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
--- /dev/null
+/*\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
--- /dev/null
+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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+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
--- /dev/null
+/*\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
--- /dev/null
+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
--- /dev/null
+/*\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
--- /dev/null
+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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+/*\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
--- /dev/null
+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