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 <getopt.h> 53#include <endian.h> 54#include <byteswap.h> 55#include <sys/poll.h> 56#include <syslog.h> 57#include <netinet/in.h> 58 59#include <infiniband/common.h> 60#include <infiniband/mad.h> 61#include <infiniband/umad.h> 62 63#include <ibdiag_common.h> 64 65static const uint8_t CLASS_SUBN_DIRECTED_ROUTE = 0x81; 66static const uint8_t CLASS_SUBN_LID_ROUTE = 0x1; 67 68#define ATTR_NODE_DESC ((uint16_t)(htons(0x10))) 69#define ATTR_NODE_INFO ((uint16_t)(htons(0x11))) 70#define ATTR_PORT_INFO ((uint16_t)(htons(0x15))) 71 72static int mad_agent; 73static int drmad_tid = 0x123; 74 75static int debug, verbose; 76 77char *argv0 = "smpdump"; 78 79typedef struct { 80 char path[64]; 81 int hop_cnt; 82} DRPath; 83 84struct drsmp { 85 uint8_t base_version; 86 uint8_t mgmt_class; 87 uint8_t class_version; 88 uint8_t method; 89 uint16_t status; 90 uint8_t hop_ptr; 91 uint8_t hop_cnt; 92 uint64_t tid; 93 uint16_t attr_id; 94 uint16_t resv; 95 uint32_t attr_mod; 96 uint64_t mkey; 97 uint16_t dr_slid; 98 uint16_t dr_dlid; 99 uint8_t reserved[28]; 100 uint8_t data[64]; 101 uint8_t initial_path[64]; 102 uint8_t return_path[64]; 103}; 104 105void 106drsmp_get_init(void *umad, DRPath *path, int attr, int mod) 107{ 108 struct drsmp *smp = (struct drsmp *)(umad_get_mad(umad)); 109 110 memset(smp, 0, sizeof (*smp)); 111 112 smp->base_version = 1; 113 smp->mgmt_class = CLASS_SUBN_DIRECTED_ROUTE; 114 smp->class_version = 1; 115 116 smp->method = 1; 117 smp->attr_id = (uint16_t)htons((uint16_t)attr); 118 smp->attr_mod = htonl(mod); 119 smp->tid = htonll(drmad_tid++); 120 smp->dr_slid = 0xffff; 121 smp->dr_dlid = 0xffff; 122 123 umad_set_addr(umad, 0xffff, 0, 0, 0); 124 125 if (path) 126 memcpy(smp->initial_path, path->path, path->hop_cnt+1); 127 128 smp->hop_cnt = path->hop_cnt; 129} 130 131void 132smp_get_init(void *umad, int lid, int attr, int mod) 133{ 134 struct drsmp *smp = (struct drsmp *)(umad_get_mad(umad)); 135 136 memset(smp, 0, sizeof (*smp)); 137 138 smp->base_version = 1; 139 smp->mgmt_class = CLASS_SUBN_LID_ROUTE; 140 smp->class_version = 1; 141 142 smp->method = 1; 143 smp->attr_id = (uint16_t)htons((uint16_t)attr); 144 smp->attr_mod = htonl(mod); 145 smp->tid = htonll(drmad_tid++); 146 147 umad_set_addr(umad, lid, 0, 0xffff, 0); 148} 149 150void 151drsmp_set_init(void *umad, DRPath *path, int attr, int mod, void *data) 152{ 153 struct drsmp *smp = (struct drsmp *)(umad_get_mad(umad)); 154 155 memset(smp, 0, sizeof (*smp)); 156 157 smp->method = 2; /* SET */ 158 smp->attr_id = (uint16_t)htons((uint16_t)attr); 159 smp->attr_mod = htonl(mod); 160 smp->tid = htonll(drmad_tid++); 161 smp->dr_slid = 0xffff; 162 smp->dr_dlid = 0xffff; 163 164 umad_set_addr(umad, 0xffff, 0, 0, 0); 165 166 if (path) 167 memcpy(smp->initial_path, path->path, path->hop_cnt+1); 168 169 if (data) 170 memcpy(smp->data, data, sizeof smp->data); 171 172 smp->hop_cnt = path->hop_cnt; 173} 174 175char * 176drmad_status_str(struct drsmp *drsmp) 177{ 178 switch (drsmp->status) { 179 case 0: 180 return "success"; 181 case ETIMEDOUT: 182 return "timeout"; 183 } 184 return "unknown error"; 185} 186 187int 188str2DRPath(char *str, DRPath *path) 189{ 190 char *s; 191 192 path->hop_cnt = -1; 193 194 DEBUG("DR str: %s", str); 195 while (str && *str) { 196 if ((s = strchr(str, ','))) 197 *s = 0; 198 path->path[++path->hop_cnt] = atoi(str); 199 if (!s) 200 break; 201 str = s+1; 202 } 203 204#if 0 205 if (path->path[0] != 0 || 206 (path->hop_cnt > 0 && dev_port && path->path[1] != dev_port)) { 207 DEBUG("hop 0 != 0 or hop 1 != dev_port"); 208 return -1; 209 } 210#endif 211 212 return path->hop_cnt; 213} 214 215void 216usage(void) 217{ 218 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); 219 fprintf(stderr, "\tDR examples:\n"); 220 fprintf(stderr, "\t\t%s -D 0,1,2,3,5 16 # NODE DESC\n", argv0); 221 fprintf(stderr, "\t\t%s -D 0,1,2 0x15 2 # PORT INFO, port 2\n", argv0); 222 fprintf(stderr, "\n\tLID routed examples:\n"); 223 fprintf(stderr, "\t\t%s 3 0x15 2 # PORT INFO, lid 3 port 2\n", argv0); 224 fprintf(stderr, "\t\t%s 0xa0 0x11 # NODE INFO, lid 0xa0\n", argv0); 225 fprintf(stderr, "\n"); 226 exit(-1); 227} 228 229int 230main(int argc, char *argv[]) 231{ 232 int dump_char = 0, timeout_ms = 1000; 233 int dev_port = 0, mgmt_class = CLASS_SUBN_LID_ROUTE, dlid = 0; 234 char *dev_name = 0; 235 void *umad; 236 struct drsmp *smp; 237 int i, portid, mod = 0, attr; 238 DRPath path; 239 uint8_t *desc; 240 int length; 241 242 static char const str_opts[] = "C:P:t:dsDVhu"; 243 static const struct option long_opts[] = { 244 { "C", 1, 0, 'C'}, 245 { "P", 1, 0, 'P'}, 246 { "debug", 0, 0, 'd'}, 247 { "sring", 0, 0, 's'}, 248 { "Direct", 0, 0, 'D'}, 249 { "timeout", 1, 0, 't'}, 250 { "Version", 0, 0, 'V'}, 251 { "help", 0, 0, 'h'}, 252 { "usage", 0, 0, 'u'}, 253 { } 254 }; 255 256 argv0 = argv[0]; 257 258 while (1) { 259 int ch = getopt_long(argc, argv, str_opts, long_opts, NULL); 260 if ( ch == -1 ) 261 break; 262 switch(ch) { 263 case 's': 264 dump_char++; 265 break; 266 case 'd': 267 debug++; 268 if (debug > 1) 269 umad_debug(debug-1); 270 break; 271 case 'D': 272 mgmt_class = CLASS_SUBN_DIRECTED_ROUTE; 273 break; 274 case 'C': 275 dev_name = optarg; 276 break; 277 case 'P': 278 dev_port = atoi(optarg); 279 break; 280 case 't': 281 timeout_ms = strtoul(optarg, 0, 0); 282 break; 283 case 'V': 284 fprintf(stderr, "%s %s\n", argv0, get_build_version() ); 285 exit(-1); 286 default: 287 usage(); 288 break; 289 } 290 } 291 argc -= optind; 292 argv += optind; 293 294 if (argc < 2) 295 usage(); 296 297 if (mgmt_class == CLASS_SUBN_DIRECTED_ROUTE && 298 str2DRPath(strdup(argv[0]), &path) < 0) 299 IBPANIC("bad path str '%s'", argv[0]); 300 301 if (mgmt_class == CLASS_SUBN_LID_ROUTE) 302 dlid = strtoul(argv[0], 0, 0); 303 304 attr = strtoul(argv[1], 0, 0); 305 if (argc > 2) 306 mod = strtoul(argv[2], 0, 0); 307 308 if (umad_init() < 0) 309 IBPANIC("can't init UMAD library"); 310 311 if ((portid = umad_open_port(dev_name, dev_port)) < 0) 312 IBPANIC("can't open UMAD port (%s:%d)", dev_name, dev_port); 313 314 if ((mad_agent = umad_register(portid, mgmt_class, 1, 0, 0)) < 0) 315 IBPANIC("Couldn't register agent for SMPs"); 316 317 if (!(umad = umad_alloc(1, umad_size() + IB_MAD_SIZE))) 318 IBPANIC("can't alloc MAD"); 319 320 smp = umad_get_mad(umad); 321 322 if (mgmt_class == CLASS_SUBN_DIRECTED_ROUTE) 323 drsmp_get_init(umad, &path, attr, mod); 324 else 325 smp_get_init(umad, dlid, attr, mod); 326 327 if (debug > 1) 328 xdump(stderr, "before send:\n", smp, 256); 329 330 length = IB_MAD_SIZE; 331 if (umad_send(portid, mad_agent, umad, length, timeout_ms, 0) < 0) 332 IBPANIC("send failed"); 333 334 if (umad_recv(portid, umad, &length, -1) != mad_agent) 335 IBPANIC("recv error: %s", drmad_status_str(smp)); 336 337 if (!dump_char) { 338 xdump(stdout, 0, smp->data, 64); 339 if (smp->status) 340 fprintf(stdout, "SMP status: 0x%x\n", ntohs(smp->status)); 341 return 0; 342 } 343 344 desc = smp->data; 345 for (i = 0; i < 64; ++i) { 346 if (!desc[i]) 347 break; 348 putchar(desc[i]); 349 } 350 putchar('\n'); 351 if (smp->status) 352 fprintf(stdout, "SMP status: 0x%x\n", ntohs(smp->status)); 353 return 0; 354} 355