1/* 2 * Copyright (c) 2004-2008 Voltaire Inc. All rights reserved. 3 * 4 * This software is available to you under a choice of one of two 5 * licenses. You may choose to be licensed under the terms of the GNU 6 * General Public License (GPL) Version 2, available from the file 7 * COPYING in the main directory of this source tree, or the 8 * OpenIB.org BSD license below: 9 * 10 * Redistribution and use in source and binary forms, with or 11 * without modification, are permitted provided that the following 12 * conditions are met: 13 * 14 * - Redistributions of source code must retain the above 15 * copyright notice, this list of conditions and the following 16 * disclaimer. 17 * 18 * - Redistributions in binary form must reproduce the above 19 * copyright notice, this list of conditions and the following 20 * disclaimer in the documentation and/or other materials 21 * provided with the distribution. 22 * 23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 * SOFTWARE. 31 * 32 */ 33 34#define _GNU_SOURCE 35 36#if HAVE_CONFIG_H 37# include <config.h> 38#endif /* HAVE_CONFIG_H */ 39 40#include <inttypes.h> 41#include <string.h> 42#include <errno.h> 43#include <stdio.h> 44#include <stdlib.h> 45#include <unistd.h> 46#include <stdarg.h> 47#include <sys/types.h> 48#include <sys/stat.h> 49#include <fcntl.h> 50#include <sys/ioctl.h> 51#include <unistd.h> 52#include <string.h> 53#include <getopt.h> 54#include <endian.h> 55#include <byteswap.h> 56#include <sys/poll.h> 57#include <syslog.h> 58#include <netinet/in.h> 59 60#include <infiniband/common.h> 61#include <infiniband/umad.h> 62#include <infiniband/mad.h> 63 64#include <ibdiag_common.h> 65 66static int debug; 67 68char *argv0 = "ibstat"; 69 70static char *node_type_str[] = { 71 "???", 72 "CA", 73 "Switch", 74 "Router", 75 "iWARP RNIC" 76}; 77 78static void 79ca_dump(umad_ca_t *ca) 80{ 81 if (!ca->node_type) 82 return; 83 printf("%s '%s'\n", ((uint)ca->node_type <= IB_NODE_MAX ? node_type_str[ca->node_type] : "???"), ca->ca_name); 84 printf("\t%s type: %s\n", ((uint)ca->node_type <= IB_NODE_MAX ? node_type_str[ca->node_type] : "???"),ca->ca_type); 85 printf("\tNumber of ports: %d\n", ca->numports); 86 printf("\tFirmware version: %s\n", ca->fw_ver); 87 printf("\tHardware version: %s\n", ca->hw_ver); 88 printf("\tNode GUID: 0x%016llx\n", (long long unsigned)ntohll(ca->node_guid)); 89 printf("\tSystem image GUID: 0x%016llx\n", (long long unsigned)ntohll(ca->system_guid)); 90} 91 92static char *port_state_str[] = { 93 "???", 94 "Down", 95 "Initializing", 96 "Armed", 97 "Active" 98}; 99 100static char *port_phy_state_str[] = { 101 "No state change", 102 "Sleep", 103 "Polling", 104 "Disabled", 105 "PortConfigurationTraining", 106 "LinkUp", 107 "LinkErrorRecovery", 108 "PhyTest" 109}; 110 111static int 112port_dump(umad_port_t *port, int alone) 113{ 114 char *pre = ""; 115 char *hdrpre = ""; 116 117 if (!port) 118 return -1; 119 120 if (!alone) { 121 pre = " "; 122 hdrpre = " "; 123 } 124 125 printf("%sPort %d:\n", hdrpre, port->portnum); 126 printf("%sState: %s\n", pre, (uint)port->state <= 4 ? port_state_str[port->state] : "???"); 127 printf("%sPhysical state: %s\n", pre, (uint)port->state <= 7 ? port_phy_state_str[port->phys_state] : "???"); 128 printf("%sRate: %d\n", pre, port->rate); 129 printf("%sBase lid: %d\n", pre, port->base_lid); 130 printf("%sLMC: %d\n", pre, port->lmc); 131 printf("%sSM lid: %d\n", pre, port->sm_lid); 132 printf("%sCapability mask: 0x%08x\n", pre, (unsigned)ntohl(port->capmask)); 133 printf("%sPort GUID: 0x%016llx\n", pre, (long long unsigned)ntohll(port->port_guid)); 134 return 0; 135} 136 137static int 138ca_stat(char *ca_name, int portnum, int no_ports) 139{ 140 umad_ca_t ca; 141 int r; 142 143 if ((r = umad_get_ca(ca_name, &ca)) < 0) 144 return r; 145 146 if (!ca.node_type) 147 return 0; 148 149 if (!no_ports && portnum >= 0) { 150 if (portnum > ca.numports || !ca.ports[portnum]) { 151 IBWARN("%s: '%s' has no port number %d - max (%d)", 152 ((uint)ca.node_type <= IB_NODE_MAX ? node_type_str[ca.node_type] : "???"), 153 ca_name, portnum, ca.numports); 154 return -1; 155 } 156 printf("%s: '%s'\n", ((uint)ca.node_type <= IB_NODE_MAX ? node_type_str[ca.node_type] : "???"), ca.ca_name); 157 port_dump(ca.ports[portnum], 1); 158 return 0; 159 } 160 161 /* print ca header */ 162 ca_dump(&ca); 163 164 if (no_ports) 165 return 0; 166 167 for (portnum = 0; portnum <= ca.numports; portnum++) 168 port_dump(ca.ports[portnum], 0); 169 170 return 0; 171} 172 173static int 174ports_list(char names[][UMAD_CA_NAME_LEN], int n) 175{ 176 uint64_t guids[64]; 177 int found, ports, i; 178 179 for (i = 0, found = 0; i < n && found < 64; i++) { 180 if ((ports = umad_get_ca_portguids(names[i], guids + found, 64 - found)) < 0) 181 return -1; 182 found += ports; 183 } 184 185 for (i = 0; i < found; i++) 186 if (guids[i]) 187 printf("0x%016llx\n", (long long unsigned)ntohll(guids[i])); 188 return found; 189} 190 191void 192usage(void) 193{ 194 fprintf(stderr, "Usage: %s [-d(ebug) -l(ist_of_cas) -s(hort) -p(ort_list) -V(ersion)] <ca_name> [portnum]\n", argv0); 195 fprintf(stderr, "\tExamples:\n"); 196 fprintf(stderr, "\t\t%s -l # list all IB devices\n", argv0); 197 fprintf(stderr, "\t\t%s mthca0 2 # stat port 2 of 'mthca0'\n", argv0); 198 exit(-1); 199} 200 201int 202main(int argc, char *argv[]) 203{ 204 char names[UMAD_MAX_DEVICES][UMAD_CA_NAME_LEN]; 205 int dev_port = -1; 206 int list_only = 0, short_format = 0, list_ports = 0; 207 int n, i; 208 209 static char const str_opts[] = "dlspVhu"; 210 static const struct option long_opts[] = { 211 { "debug", 0, 0, 'd'}, 212 { "list_of_cas", 0, 0, 'l'}, 213 { "short", 0, 0, 's'}, 214 { "port_list", 0, 0, 'p'}, 215 { "Version", 0, 0, 'V'}, 216 { "help", 0, 0, 'h'}, 217 { "usage", 0, 0, 'u'}, 218 { } 219 }; 220 221 argv0 = argv[0]; 222 223 while (1) { 224 int ch = getopt_long(argc, argv, str_opts, long_opts, NULL); 225 if ( ch == -1 ) 226 break; 227 switch(ch) { 228 case 'd': 229 debug++; 230 break; 231 case 'l': 232 list_only++; 233 break; 234 case 's': 235 short_format++; 236 break; 237 case 'p': 238 list_ports++; 239 break; 240 case 'V': 241 fprintf(stderr, "%s %s\n", argv0, get_build_version() ); 242 exit(-1); 243 default: 244 usage(); 245 break; 246 } 247 } 248 argc -= optind; 249 argv += optind; 250 251 if (argc > 1) 252 dev_port = strtol(argv[1], 0, 0); 253 254 if (umad_init() < 0) 255 IBPANIC("can't init UMAD library"); 256 257 if ((n = umad_get_cas_names(names, UMAD_MAX_DEVICES)) < 0) 258 IBPANIC("can't list IB device names"); 259 260 if (argc) { 261 for (i = 0; i < n; i++) 262 if (!strncmp(names[i], argv[0], sizeof names[i])) 263 break; 264 if (i >= n) 265 IBPANIC("'%s' IB device can't be found", argv[0]); 266 267 strncpy(names[i], argv[0], sizeof names[i]); 268 n = 1; 269 } 270 271 if (list_ports) { 272 if (ports_list(names, n) < 0) 273 IBPANIC("can't list ports"); 274 return 0; 275 } 276 277 if (!list_only && argc) { 278 if (ca_stat(argv[0], dev_port, short_format) < 0) 279 IBPANIC("stat of IB device '%s' failed", argv[0]); 280 return 0; 281 } 282 283 for (i = 0; i < n; i++) { 284 if (list_only) 285 printf("%s\n", names[i]); 286 else 287 if (ca_stat(names[i], -1, short_format) < 0) 288 IBPANIC("stat of IB device '%s' failed", names[i]); 289 } 290 291 return 0; 292} 293