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 52 #include <infiniband/umad.h> 53 54 #include <ibdiag_common.h> 55 56 static char *node_type_str[] = { 57 "???", 58 "CA", 59 "Switch", 60 "Router", 61 "iWARP RNIC" 62 }; 63 64 static void ca_dump(umad_ca_t * ca) 65 { 66 if (!ca->node_type) 67 return; 68 printf("%s '%s'\n", 69 ((unsigned)ca->node_type <= 70 IB_NODE_MAX ? node_type_str[ca->node_type] : "???"), 71 ca->ca_name); 72 printf("\t%s type: %s\n", 73 ((unsigned)ca->node_type <= 74 IB_NODE_MAX ? node_type_str[ca->node_type] : "???"), 75 ca->ca_type); 76 printf("\tNumber of ports: %d\n", ca->numports); 77 printf("\tFirmware version: %s\n", ca->fw_ver); 78 printf("\tHardware version: %s\n", ca->hw_ver); 79 printf("\tNode GUID: 0x%016" PRIx64 "\n", ntohll(ca->node_guid)); 80 printf("\tSystem image GUID: 0x%016" PRIx64 "\n", 81 ntohll(ca->system_guid)); 82 } 83 84 static char *port_state_str[] = { 85 "???", 86 "Down", 87 "Initializing", 88 "Armed", 89 "Active" 90 }; 91 92 static char *port_phy_state_str[] = { 93 "No state change", 94 "Sleep", 95 "Polling", 96 "Disabled", 97 "PortConfigurationTraining", 98 "LinkUp", 99 "LinkErrorRecovery", 100 "PhyTest" 101 }; 102 103 static int ret_code(void) 104 { 105 int e = errno; 106 107 if (e > 0) 108 return -e; 109 return e; 110 } 111 112 int sys_read_string(const char *dir_name, const char *file_name, char *str, int max_len) 113 { 114 char path[256], *s; 115 size_t len; 116 117 snprintf(path, sizeof(path), "%s/%s", dir_name, file_name); 118 119 for (s = &path[0]; *s != '\0'; s++) 120 if (*s == '/') 121 *s = '.'; 122 123 len = max_len; 124 if (sysctlbyname(&path[1], str, &len, NULL, 0) == -1) 125 return ret_code(); 126 127 str[(len < max_len) ? len : max_len - 1] = 0; 128 129 if ((s = strrchr(str, '\n'))) 130 *s = 0; 131 132 return 0; 133 } 134 135 static int is_fdr10(umad_port_t *port) 136 { 137 char port_dir[256]; 138 char rate[32]; 139 int len, fdr10 = 0; 140 char *p; 141 142 len = snprintf(port_dir, sizeof(port_dir), "%s/%s/%s/%d", 143 SYS_INFINIBAND, port->ca_name, SYS_CA_PORTS_DIR, 144 port->portnum); 145 if (len < 0 || len > sizeof(port_dir)) 146 goto done; 147 148 if (sys_read_string(port_dir, SYS_PORT_RATE, rate, sizeof(rate)) == 0) { 149 if ((p = strchr(rate, ')'))) { 150 if (!strncasecmp(p - 5, "fdr10", 5)) 151 fdr10 = 1; 152 } 153 } 154 155 done: 156 return fdr10; 157 } 158 159 static int port_dump(umad_port_t * port, int alone) 160 { 161 char *pre = ""; 162 char *hdrpre = ""; 163 164 if (!port) 165 return -1; 166 167 if (!alone) { 168 pre = " "; 169 hdrpre = " "; 170 } 171 172 printf("%sPort %d:\n", hdrpre, port->portnum); 173 printf("%sState: %s\n", pre, 174 (unsigned)port->state <= 175 4 ? port_state_str[port->state] : "???"); 176 printf("%sPhysical state: %s\n", pre, 177 (unsigned)port->phys_state <= 178 7 ? port_phy_state_str[port->phys_state] : "???"); 179 if (is_fdr10(port)) 180 printf("%sRate: %d (FDR10)\n", pre, port->rate); 181 else 182 if (port->rate != 2) 183 printf("%sRate: %d\n", pre, port->rate); 184 else 185 printf("%sRate: 2.5\n", pre); 186 printf("%sBase lid: %d\n", pre, port->base_lid); 187 printf("%sLMC: %d\n", pre, port->lmc); 188 printf("%sSM lid: %d\n", pre, port->sm_lid); 189 printf("%sCapability mask: 0x%08x\n", pre, ntohl(port->capmask)); 190 printf("%sPort GUID: 0x%016" PRIx64 "\n", pre, ntohll(port->port_guid)); 191 #ifdef HAVE_UMAD_PORT_LINK_LAYER 192 printf("%sLink layer: %s\n", pre, port->link_layer); 193 #endif 194 return 0; 195 } 196 197 static int ca_stat(char *ca_name, int portnum, int no_ports) 198 { 199 umad_ca_t ca; 200 int r; 201 202 if ((r = umad_get_ca(ca_name, &ca)) < 0) 203 return r; 204 205 if (!ca.node_type) 206 return 0; 207 208 if (!no_ports && portnum >= 0) { 209 if (portnum > ca.numports || !ca.ports[portnum]) { 210 IBWARN("%s: '%s' has no port number %d - max (%d)", 211 ((unsigned)ca.node_type <= 212 IB_NODE_MAX ? node_type_str[ca.node_type] : 213 "???"), ca_name, portnum, ca.numports); 214 return -1; 215 } 216 printf("%s: '%s'\n", 217 ((unsigned)ca.node_type <= 218 IB_NODE_MAX ? node_type_str[ca.node_type] : "???"), 219 ca.ca_name); 220 port_dump(ca.ports[portnum], 1); 221 return 0; 222 } 223 224 /* print ca header */ 225 ca_dump(&ca); 226 227 if (no_ports) 228 return 0; 229 230 for (portnum = 0; portnum <= ca.numports; portnum++) 231 port_dump(ca.ports[portnum], 0); 232 233 return 0; 234 } 235 236 static int ports_list(char names[][UMAD_CA_NAME_LEN], int n) 237 { 238 uint64_t guids[64]; 239 int found, ports, i; 240 241 for (i = 0, found = 0; i < n && found < 64; i++) { 242 if ((ports = 243 umad_get_ca_portguids(names[i], guids + found, 244 64 - found)) < 0) 245 return -1; 246 found += ports; 247 } 248 249 for (i = 0; i < found; i++) 250 if (guids[i]) 251 printf("0x%016" PRIx64 "\n", ntohll(guids[i])); 252 return found; 253 } 254 255 static int list_only, short_format, list_ports; 256 257 static int process_opt(void *context, int ch, char *optarg) 258 { 259 switch (ch) { 260 case 'l': 261 list_only++; 262 break; 263 case 's': 264 short_format++; 265 break; 266 case 'p': 267 list_ports++; 268 break; 269 default: 270 return -1; 271 } 272 return 0; 273 } 274 275 int main(int argc, char *argv[]) 276 { 277 char names[UMAD_MAX_DEVICES][UMAD_CA_NAME_LEN]; 278 int dev_port = -1; 279 int n, i; 280 281 const struct ibdiag_opt opts[] = { 282 {"list_of_cas", 'l', 0, NULL, "list all IB devices"}, 283 {"short", 's', 0, NULL, "short output"}, 284 {"port_list", 'p', 0, NULL, "show port list"}, 285 {0} 286 }; 287 char usage_args[] = "<ca_name> [portnum]"; 288 const char *usage_examples[] = { 289 "-l # list all IB devices", 290 "mthca0 2 # stat port 2 of 'mthca0'", 291 NULL 292 }; 293 294 ibdiag_process_opts(argc, argv, NULL, "CDeGKLPsty", opts, process_opt, 295 usage_args, usage_examples); 296 297 argc -= optind; 298 argv += optind; 299 300 if (argc > 1) 301 dev_port = strtol(argv[1], 0, 0); 302 303 if (umad_init() < 0) 304 IBPANIC("can't init UMAD library"); 305 306 if ((n = umad_get_cas_names(names, UMAD_MAX_DEVICES)) < 0) 307 IBPANIC("can't list IB device names"); 308 309 if (argc) { 310 for (i = 0; i < n; i++) 311 if (!strncmp(names[i], argv[0], sizeof names[i])) 312 break; 313 if (i >= n) 314 IBPANIC("'%s' IB device can't be found", argv[0]); 315 316 strncpy(names[0], argv[0], sizeof(names[0])-1); 317 names[0][sizeof(names[0])-1] = '\0'; 318 n = 1; 319 } 320 321 if (list_ports) { 322 if (ports_list(names, n) < 0) 323 IBPANIC("can't list ports"); 324 return 0; 325 } 326 327 for (i = 0; i < n; i++) { 328 if (list_only) 329 printf("%s\n", names[i]); 330 else if (ca_stat(names[i], dev_port, short_format) < 0) 331 IBPANIC("stat of IB device '%s' failed", names[i]); 332 } 333 334 return 0; 335 } 336