smpdump.c revision 219820
1139804Simp/* 265534Salfred * Copyright (c) 2004-2008 Voltaire Inc. All rights reserved. 365534Salfred * 461837Salfred * This software is available to you under a choice of one of two 561837Salfred * licenses. You may choose to be licensed under the terms of the GNU 661837Salfred * General Public License (GPL) Version 2, available from the file 761837Salfred * COPYING in the main directory of this source tree, or the 861837Salfred * OpenIB.org BSD license below: 961837Salfred * 1061837Salfred * Redistribution and use in source and binary forms, with or 1161837Salfred * without modification, are permitted provided that the following 1261837Salfred * conditions are met: 1361837Salfred * 1461837Salfred * - Redistributions of source code must retain the above 1561837Salfred * copyright notice, this list of conditions and the following 1661837Salfred * disclaimer. 1761837Salfred * 1861837Salfred * - Redistributions in binary form must reproduce the above 1961837Salfred * copyright notice, this list of conditions and the following 2061837Salfred * disclaimer in the documentation and/or other materials 2161837Salfred * provided with the distribution. 2261837Salfred * 2361837Salfred * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 2461837Salfred * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 2561837Salfred * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 2661837Salfred * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 2761837Salfred * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28116182Sobrien * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29116182Sobrien * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30116182Sobrien * SOFTWARE. 3161837Salfred * 3261837Salfred */ 3377598Sjesper 3461837Salfred#define _GNU_SOURCE 3561837Salfred 3661837Salfred#if HAVE_CONFIG_H 3761837Salfred# include <config.h> 38129920Srwatson#endif /* HAVE_CONFIG_H */ 3961837Salfred 4061837Salfred#include <inttypes.h> 41129876Sphk#include <string.h> 42129920Srwatson#include <errno.h> 4361837Salfred#include <stdio.h> 4465534Salfred#include <stdlib.h> 4561837Salfred#include <unistd.h> 4661837Salfred#include <stdarg.h> 4761837Salfred#include <sys/types.h> 4861837Salfred#include <sys/stat.h> 49129920Srwatson#include <fcntl.h> 50129920Srwatson#include <sys/ioctl.h> 51129920Srwatson#include <unistd.h> 52129920Srwatson#include <getopt.h> 53129920Srwatson#include <endian.h> 54129920Srwatson#include <byteswap.h> 5561837Salfred#include <sys/poll.h> 5661837Salfred#include <syslog.h> 5761837Salfred#include <netinet/in.h> 5861837Salfred 5961837Salfred#include <infiniband/common.h> 6065534Salfred#include <infiniband/mad.h> 6165534Salfred#include <infiniband/umad.h> 6265534Salfred 6365534Salfred#include <ibdiag_common.h> 6465534Salfred 6565534Salfredstatic const uint8_t CLASS_SUBN_DIRECTED_ROUTE = 0x81; 6665534Salfredstatic const uint8_t CLASS_SUBN_LID_ROUTE = 0x1; 6761837Salfred 6861837Salfred#define ATTR_NODE_DESC ((uint16_t)(htons(0x10))) 6961837Salfred#define ATTR_NODE_INFO ((uint16_t)(htons(0x11))) 7061837Salfred#define ATTR_PORT_INFO ((uint16_t)(htons(0x15))) 7161837Salfred 7261837Salfredstatic int mad_agent; 7361837Salfredstatic int drmad_tid = 0x123; 7461837Salfred 7561837Salfredstatic int debug, verbose; 7661837Salfred 7761837Salfredchar *argv0 = "smpdump"; 78129920Srwatson 7961837Salfredtypedef struct { 8061837Salfred char path[64]; 8161837Salfred int hop_cnt; 82129920Srwatson} DRPath; 8361837Salfred 8461837Salfredstruct drsmp { 8561837Salfred uint8_t base_version; 86129920Srwatson uint8_t mgmt_class; 8761837Salfred uint8_t class_version; 8861837Salfred uint8_t method; 8961837Salfred uint16_t status; 9061837Salfred uint8_t hop_ptr; 9161837Salfred uint8_t hop_cnt; 9261837Salfred uint64_t tid; 9361837Salfred uint16_t attr_id; 94129920Srwatson uint16_t resv; 9561837Salfred uint32_t attr_mod; 9661837Salfred uint64_t mkey; 9761837Salfred uint16_t dr_slid; 9861837Salfred uint16_t dr_dlid; 9961837Salfred uint8_t reserved[28]; 10061837Salfred uint8_t data[64]; 10161837Salfred uint8_t initial_path[64]; 10261837Salfred uint8_t return_path[64]; 10361837Salfred}; 10461837Salfred 10561837Salfredvoid 10661837Salfreddrsmp_get_init(void *umad, DRPath *path, int attr, int mod) 10761837Salfred{ 10861837Salfred struct drsmp *smp = (struct drsmp *)(umad_get_mad(umad)); 10961837Salfred 11061837Salfred memset(smp, 0, sizeof (*smp)); 11161837Salfred 11261837Salfred smp->base_version = 1; 11361837Salfred smp->mgmt_class = CLASS_SUBN_DIRECTED_ROUTE; 11461837Salfred smp->class_version = 1; 11561837Salfred 116129920Srwatson smp->method = 1; 11761837Salfred smp->attr_id = (uint16_t)htons((uint16_t)attr); 11861837Salfred smp->attr_mod = htonl(mod); 119129920Srwatson smp->tid = htonll(drmad_tid++); 120129920Srwatson smp->dr_slid = 0xffff; 12161837Salfred smp->dr_dlid = 0xffff; 122129920Srwatson 12361837Salfred umad_set_addr(umad, 0xffff, 0, 0, 0); 12461837Salfred 12561837Salfred if (path) 12661837Salfred memcpy(smp->initial_path, path->path, path->hop_cnt+1); 12761837Salfred 12861837Salfred smp->hop_cnt = path->hop_cnt; 12961837Salfred} 130129920Srwatson 13161837Salfredvoid 13261837Salfredsmp_get_init(void *umad, int lid, int attr, int mod) 13361837Salfred{ 134111119Simp struct drsmp *smp = (struct drsmp *)(umad_get_mad(umad)); 13561837Salfred 13661837Salfred memset(smp, 0, sizeof (*smp)); 13761837Salfred 13861837Salfred smp->base_version = 1; 13961837Salfred smp->mgmt_class = CLASS_SUBN_LID_ROUTE; 14063645Salfred smp->class_version = 1; 14163645Salfred 14263645Salfred smp->method = 1; 14363645Salfred smp->attr_id = (uint16_t)htons((uint16_t)attr); 14463645Salfred smp->attr_mod = htonl(mod); 14563645Salfred smp->tid = htonll(drmad_tid++); 14665534Salfred 14765534Salfred umad_set_addr(umad, lid, 0, 0xffff, 0); 14865534Salfred} 14965534Salfred 15061837Salfredvoid 15161837Salfreddrsmp_set_init(void *umad, DRPath *path, int attr, int mod, void *data) 15261837Salfred{ 15361837Salfred struct drsmp *smp = (struct drsmp *)(umad_get_mad(umad)); 15461837Salfred 15561837Salfred memset(smp, 0, sizeof (*smp)); 15661837Salfred 15761837Salfred smp->method = 2; /* SET */ 15861837Salfred smp->attr_id = (uint16_t)htons((uint16_t)attr); 15961837Salfred smp->attr_mod = htonl(mod); 16061837Salfred smp->tid = htonll(drmad_tid++); 16161837Salfred smp->dr_slid = 0xffff; 16261837Salfred 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