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