1*d6b92ffaSHans Petter Selasky /* 2*d6b92ffaSHans Petter Selasky * Copyright (c) 2004-2009 Voltaire Inc. All rights reserved. 3*d6b92ffaSHans Petter Selasky * 4*d6b92ffaSHans Petter Selasky * This software is available to you under a choice of one of two 5*d6b92ffaSHans Petter Selasky * licenses. You may choose to be licensed under the terms of the GNU 6*d6b92ffaSHans Petter Selasky * General Public License (GPL) Version 2, available from the file 7*d6b92ffaSHans Petter Selasky * COPYING in the main directory of this source tree, or the 8*d6b92ffaSHans Petter Selasky * OpenIB.org BSD license below: 9*d6b92ffaSHans Petter Selasky * 10*d6b92ffaSHans Petter Selasky * Redistribution and use in source and binary forms, with or 11*d6b92ffaSHans Petter Selasky * without modification, are permitted provided that the following 12*d6b92ffaSHans Petter Selasky * conditions are met: 13*d6b92ffaSHans Petter Selasky * 14*d6b92ffaSHans Petter Selasky * - Redistributions of source code must retain the above 15*d6b92ffaSHans Petter Selasky * copyright notice, this list of conditions and the following 16*d6b92ffaSHans Petter Selasky * disclaimer. 17*d6b92ffaSHans Petter Selasky * 18*d6b92ffaSHans Petter Selasky * - Redistributions in binary form must reproduce the above 19*d6b92ffaSHans Petter Selasky * copyright notice, this list of conditions and the following 20*d6b92ffaSHans Petter Selasky * disclaimer in the documentation and/or other materials 21*d6b92ffaSHans Petter Selasky * provided with the distribution. 22*d6b92ffaSHans Petter Selasky * 23*d6b92ffaSHans Petter Selasky * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24*d6b92ffaSHans Petter Selasky * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25*d6b92ffaSHans Petter Selasky * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26*d6b92ffaSHans Petter Selasky * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27*d6b92ffaSHans Petter Selasky * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28*d6b92ffaSHans Petter Selasky * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29*d6b92ffaSHans Petter Selasky * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30*d6b92ffaSHans Petter Selasky * SOFTWARE. 31*d6b92ffaSHans Petter Selasky * 32*d6b92ffaSHans Petter Selasky */ 33*d6b92ffaSHans Petter Selasky 34*d6b92ffaSHans Petter Selasky #define _GNU_SOURCE 35*d6b92ffaSHans Petter Selasky 36*d6b92ffaSHans Petter Selasky #if HAVE_CONFIG_H 37*d6b92ffaSHans Petter Selasky # include <config.h> 38*d6b92ffaSHans Petter Selasky #endif /* HAVE_CONFIG_H */ 39*d6b92ffaSHans Petter Selasky 40*d6b92ffaSHans Petter Selasky #include <inttypes.h> 41*d6b92ffaSHans Petter Selasky #include <string.h> 42*d6b92ffaSHans Petter Selasky #include <errno.h> 43*d6b92ffaSHans Petter Selasky #include <stdio.h> 44*d6b92ffaSHans Petter Selasky #include <stdlib.h> 45*d6b92ffaSHans Petter Selasky #include <getopt.h> 46*d6b92ffaSHans Petter Selasky #include <netinet/in.h> 47*d6b92ffaSHans Petter Selasky 48*d6b92ffaSHans Petter Selasky #include <infiniband/mad.h> 49*d6b92ffaSHans Petter Selasky #include <infiniband/umad.h> 50*d6b92ffaSHans Petter Selasky 51*d6b92ffaSHans Petter Selasky #include <ibdiag_common.h> 52*d6b92ffaSHans Petter Selasky 53*d6b92ffaSHans Petter Selasky static int mad_agent; 54*d6b92ffaSHans Petter Selasky static int drmad_tid = 0x123; 55*d6b92ffaSHans Petter Selasky 56*d6b92ffaSHans Petter Selasky typedef struct { 57*d6b92ffaSHans Petter Selasky char path[64]; 58*d6b92ffaSHans Petter Selasky int hop_cnt; 59*d6b92ffaSHans Petter Selasky } DRPath; 60*d6b92ffaSHans Petter Selasky 61*d6b92ffaSHans Petter Selasky struct drsmp { 62*d6b92ffaSHans Petter Selasky uint8_t base_version; 63*d6b92ffaSHans Petter Selasky uint8_t mgmt_class; 64*d6b92ffaSHans Petter Selasky uint8_t class_version; 65*d6b92ffaSHans Petter Selasky uint8_t method; 66*d6b92ffaSHans Petter Selasky uint16_t status; 67*d6b92ffaSHans Petter Selasky uint8_t hop_ptr; 68*d6b92ffaSHans Petter Selasky uint8_t hop_cnt; 69*d6b92ffaSHans Petter Selasky uint64_t tid; 70*d6b92ffaSHans Petter Selasky uint16_t attr_id; 71*d6b92ffaSHans Petter Selasky uint16_t resv; 72*d6b92ffaSHans Petter Selasky uint32_t attr_mod; 73*d6b92ffaSHans Petter Selasky uint64_t mkey; 74*d6b92ffaSHans Petter Selasky uint16_t dr_slid; 75*d6b92ffaSHans Petter Selasky uint16_t dr_dlid; 76*d6b92ffaSHans Petter Selasky uint8_t reserved[28]; 77*d6b92ffaSHans Petter Selasky uint8_t data[64]; 78*d6b92ffaSHans Petter Selasky uint8_t initial_path[64]; 79*d6b92ffaSHans Petter Selasky uint8_t return_path[64]; 80*d6b92ffaSHans Petter Selasky }; 81*d6b92ffaSHans Petter Selasky 82*d6b92ffaSHans Petter Selasky void drsmp_get_init(void *umad, DRPath * path, int attr, int mod) 83*d6b92ffaSHans Petter Selasky { 84*d6b92ffaSHans Petter Selasky struct drsmp *smp = (struct drsmp *)(umad_get_mad(umad)); 85*d6b92ffaSHans Petter Selasky 86*d6b92ffaSHans Petter Selasky memset(smp, 0, sizeof(*smp)); 87*d6b92ffaSHans Petter Selasky 88*d6b92ffaSHans Petter Selasky smp->base_version = 1; 89*d6b92ffaSHans Petter Selasky smp->mgmt_class = IB_SMI_DIRECT_CLASS; 90*d6b92ffaSHans Petter Selasky smp->class_version = 1; 91*d6b92ffaSHans Petter Selasky 92*d6b92ffaSHans Petter Selasky smp->method = 1; 93*d6b92ffaSHans Petter Selasky smp->attr_id = (uint16_t) htons((uint16_t) attr); 94*d6b92ffaSHans Petter Selasky smp->attr_mod = htonl(mod); 95*d6b92ffaSHans Petter Selasky smp->tid = htonll(drmad_tid++); 96*d6b92ffaSHans Petter Selasky smp->dr_slid = 0xffff; 97*d6b92ffaSHans Petter Selasky smp->dr_dlid = 0xffff; 98*d6b92ffaSHans Petter Selasky 99*d6b92ffaSHans Petter Selasky umad_set_addr(umad, 0xffff, 0, 0, 0); 100*d6b92ffaSHans Petter Selasky 101*d6b92ffaSHans Petter Selasky if (path) 102*d6b92ffaSHans Petter Selasky memcpy(smp->initial_path, path->path, path->hop_cnt + 1); 103*d6b92ffaSHans Petter Selasky 104*d6b92ffaSHans Petter Selasky smp->hop_cnt = (uint8_t) path->hop_cnt; 105*d6b92ffaSHans Petter Selasky } 106*d6b92ffaSHans Petter Selasky 107*d6b92ffaSHans Petter Selasky void smp_get_init(void *umad, int lid, int attr, int mod) 108*d6b92ffaSHans Petter Selasky { 109*d6b92ffaSHans Petter Selasky struct drsmp *smp = (struct drsmp *)(umad_get_mad(umad)); 110*d6b92ffaSHans Petter Selasky 111*d6b92ffaSHans Petter Selasky memset(smp, 0, sizeof(*smp)); 112*d6b92ffaSHans Petter Selasky 113*d6b92ffaSHans Petter Selasky smp->base_version = 1; 114*d6b92ffaSHans Petter Selasky smp->mgmt_class = IB_SMI_CLASS; 115*d6b92ffaSHans Petter Selasky smp->class_version = 1; 116*d6b92ffaSHans Petter Selasky 117*d6b92ffaSHans Petter Selasky smp->method = 1; 118*d6b92ffaSHans Petter Selasky smp->attr_id = (uint16_t) htons((uint16_t) attr); 119*d6b92ffaSHans Petter Selasky smp->attr_mod = htonl(mod); 120*d6b92ffaSHans Petter Selasky smp->tid = htonll(drmad_tid++); 121*d6b92ffaSHans Petter Selasky 122*d6b92ffaSHans Petter Selasky umad_set_addr(umad, lid, 0, 0, 0); 123*d6b92ffaSHans Petter Selasky } 124*d6b92ffaSHans Petter Selasky 125*d6b92ffaSHans Petter Selasky void drsmp_set_init(void *umad, DRPath * path, int attr, int mod, void *data) 126*d6b92ffaSHans Petter Selasky { 127*d6b92ffaSHans Petter Selasky struct drsmp *smp = (struct drsmp *)(umad_get_mad(umad)); 128*d6b92ffaSHans Petter Selasky 129*d6b92ffaSHans Petter Selasky memset(smp, 0, sizeof(*smp)); 130*d6b92ffaSHans Petter Selasky 131*d6b92ffaSHans Petter Selasky smp->method = 2; /* SET */ 132*d6b92ffaSHans Petter Selasky smp->attr_id = (uint16_t) htons((uint16_t) attr); 133*d6b92ffaSHans Petter Selasky smp->attr_mod = htonl(mod); 134*d6b92ffaSHans Petter Selasky smp->tid = htonll(drmad_tid++); 135*d6b92ffaSHans Petter Selasky smp->dr_slid = 0xffff; 136*d6b92ffaSHans Petter Selasky smp->dr_dlid = 0xffff; 137*d6b92ffaSHans Petter Selasky 138*d6b92ffaSHans Petter Selasky umad_set_addr(umad, 0xffff, 0, 0, 0); 139*d6b92ffaSHans Petter Selasky 140*d6b92ffaSHans Petter Selasky if (path) 141*d6b92ffaSHans Petter Selasky memcpy(smp->initial_path, path->path, path->hop_cnt + 1); 142*d6b92ffaSHans Petter Selasky 143*d6b92ffaSHans Petter Selasky if (data) 144*d6b92ffaSHans Petter Selasky memcpy(smp->data, data, sizeof smp->data); 145*d6b92ffaSHans Petter Selasky 146*d6b92ffaSHans Petter Selasky smp->hop_cnt = (uint8_t) path->hop_cnt; 147*d6b92ffaSHans Petter Selasky } 148*d6b92ffaSHans Petter Selasky 149*d6b92ffaSHans Petter Selasky char *drmad_status_str(struct drsmp *drsmp) 150*d6b92ffaSHans Petter Selasky { 151*d6b92ffaSHans Petter Selasky switch (drsmp->status) { 152*d6b92ffaSHans Petter Selasky case 0: 153*d6b92ffaSHans Petter Selasky return "success"; 154*d6b92ffaSHans Petter Selasky case ETIMEDOUT: 155*d6b92ffaSHans Petter Selasky return "timeout"; 156*d6b92ffaSHans Petter Selasky } 157*d6b92ffaSHans Petter Selasky return "unknown error"; 158*d6b92ffaSHans Petter Selasky } 159*d6b92ffaSHans Petter Selasky 160*d6b92ffaSHans Petter Selasky int str2DRPath(char *str, DRPath * path) 161*d6b92ffaSHans Petter Selasky { 162*d6b92ffaSHans Petter Selasky char *s; 163*d6b92ffaSHans Petter Selasky 164*d6b92ffaSHans Petter Selasky path->hop_cnt = -1; 165*d6b92ffaSHans Petter Selasky 166*d6b92ffaSHans Petter Selasky DEBUG("DR str: %s", str); 167*d6b92ffaSHans Petter Selasky while (str && *str) { 168*d6b92ffaSHans Petter Selasky if ((s = strchr(str, ','))) 169*d6b92ffaSHans Petter Selasky *s = 0; 170*d6b92ffaSHans Petter Selasky path->path[++path->hop_cnt] = (char)atoi(str); 171*d6b92ffaSHans Petter Selasky if (!s) 172*d6b92ffaSHans Petter Selasky break; 173*d6b92ffaSHans Petter Selasky str = s + 1; 174*d6b92ffaSHans Petter Selasky } 175*d6b92ffaSHans Petter Selasky 176*d6b92ffaSHans Petter Selasky #if 0 177*d6b92ffaSHans Petter Selasky if (path->path[0] != 0 || 178*d6b92ffaSHans Petter Selasky (path->hop_cnt > 0 && dev_port && path->path[1] != dev_port)) { 179*d6b92ffaSHans Petter Selasky DEBUG("hop 0 != 0 or hop 1 != dev_port"); 180*d6b92ffaSHans Petter Selasky return -1; 181*d6b92ffaSHans Petter Selasky } 182*d6b92ffaSHans Petter Selasky #endif 183*d6b92ffaSHans Petter Selasky 184*d6b92ffaSHans Petter Selasky return path->hop_cnt; 185*d6b92ffaSHans Petter Selasky } 186*d6b92ffaSHans Petter Selasky 187*d6b92ffaSHans Petter Selasky static int dump_char, mgmt_class = IB_SMI_CLASS; 188*d6b92ffaSHans Petter Selasky 189*d6b92ffaSHans Petter Selasky static int process_opt(void *context, int ch, char *optarg) 190*d6b92ffaSHans Petter Selasky { 191*d6b92ffaSHans Petter Selasky switch (ch) { 192*d6b92ffaSHans Petter Selasky case 's': 193*d6b92ffaSHans Petter Selasky dump_char++; 194*d6b92ffaSHans Petter Selasky break; 195*d6b92ffaSHans Petter Selasky case 'D': 196*d6b92ffaSHans Petter Selasky mgmt_class = IB_SMI_DIRECT_CLASS; 197*d6b92ffaSHans Petter Selasky break; 198*d6b92ffaSHans Petter Selasky case 'L': 199*d6b92ffaSHans Petter Selasky mgmt_class = IB_SMI_CLASS; 200*d6b92ffaSHans Petter Selasky break; 201*d6b92ffaSHans Petter Selasky default: 202*d6b92ffaSHans Petter Selasky return -1; 203*d6b92ffaSHans Petter Selasky } 204*d6b92ffaSHans Petter Selasky return 0; 205*d6b92ffaSHans Petter Selasky } 206*d6b92ffaSHans Petter Selasky 207*d6b92ffaSHans Petter Selasky #ifndef strdupa 208*d6b92ffaSHans Petter Selasky #define strdupa(_s) \ 209*d6b92ffaSHans Petter Selasky ({ \ 210*d6b92ffaSHans Petter Selasky char *_d; \ 211*d6b92ffaSHans Petter Selasky int _len; \ 212*d6b92ffaSHans Petter Selasky \ 213*d6b92ffaSHans Petter Selasky _len = strlen(_s) + 1; \ 214*d6b92ffaSHans Petter Selasky _d = alloca(_len); \ 215*d6b92ffaSHans Petter Selasky if (_d) \ 216*d6b92ffaSHans Petter Selasky memcpy(_d, _s, _len); \ 217*d6b92ffaSHans Petter Selasky _d; \ 218*d6b92ffaSHans Petter Selasky }) 219*d6b92ffaSHans Petter Selasky #endif 220*d6b92ffaSHans Petter Selasky 221*d6b92ffaSHans Petter Selasky int main(int argc, char *argv[]) 222*d6b92ffaSHans Petter Selasky { 223*d6b92ffaSHans Petter Selasky int dlid = 0; 224*d6b92ffaSHans Petter Selasky void *umad; 225*d6b92ffaSHans Petter Selasky struct drsmp *smp; 226*d6b92ffaSHans Petter Selasky int i, portid, mod = 0, attr; 227*d6b92ffaSHans Petter Selasky DRPath path; 228*d6b92ffaSHans Petter Selasky uint8_t *desc; 229*d6b92ffaSHans Petter Selasky int length; 230*d6b92ffaSHans Petter Selasky 231*d6b92ffaSHans Petter Selasky const struct ibdiag_opt opts[] = { 232*d6b92ffaSHans Petter Selasky {"string", 's', 0, NULL, ""}, 233*d6b92ffaSHans Petter Selasky {0} 234*d6b92ffaSHans Petter Selasky }; 235*d6b92ffaSHans Petter Selasky char usage_args[] = "<dlid|dr_path> <attr> [mod]"; 236*d6b92ffaSHans Petter Selasky const char *usage_examples[] = { 237*d6b92ffaSHans Petter Selasky " -- DR routed examples:", 238*d6b92ffaSHans Petter Selasky "-D 0,1,2,3,5 16 # NODE DESC", 239*d6b92ffaSHans Petter Selasky "-D 0,1,2 0x15 2 # PORT INFO, port 2", 240*d6b92ffaSHans Petter Selasky " -- LID routed examples:", 241*d6b92ffaSHans Petter Selasky "3 0x15 2 # PORT INFO, lid 3 port 2", 242*d6b92ffaSHans Petter Selasky "0xa0 0x11 # NODE INFO, lid 0xa0", 243*d6b92ffaSHans Petter Selasky NULL 244*d6b92ffaSHans Petter Selasky }; 245*d6b92ffaSHans Petter Selasky 246*d6b92ffaSHans Petter Selasky ibd_timeout = 1000; 247*d6b92ffaSHans Petter Selasky 248*d6b92ffaSHans Petter Selasky ibdiag_process_opts(argc, argv, NULL, "GKs", opts, process_opt, 249*d6b92ffaSHans Petter Selasky usage_args, usage_examples); 250*d6b92ffaSHans Petter Selasky 251*d6b92ffaSHans Petter Selasky argc -= optind; 252*d6b92ffaSHans Petter Selasky argv += optind; 253*d6b92ffaSHans Petter Selasky 254*d6b92ffaSHans Petter Selasky if (argc < 2) 255*d6b92ffaSHans Petter Selasky ibdiag_show_usage(); 256*d6b92ffaSHans Petter Selasky 257*d6b92ffaSHans Petter Selasky if (mgmt_class == IB_SMI_DIRECT_CLASS && 258*d6b92ffaSHans Petter Selasky str2DRPath(strdupa(argv[0]), &path) < 0) 259*d6b92ffaSHans Petter Selasky IBPANIC("bad path str '%s'", argv[0]); 260*d6b92ffaSHans Petter Selasky 261*d6b92ffaSHans Petter Selasky if (mgmt_class == IB_SMI_CLASS) 262*d6b92ffaSHans Petter Selasky dlid = strtoul(argv[0], 0, 0); 263*d6b92ffaSHans Petter Selasky 264*d6b92ffaSHans Petter Selasky attr = strtoul(argv[1], 0, 0); 265*d6b92ffaSHans Petter Selasky if (argc > 2) 266*d6b92ffaSHans Petter Selasky mod = strtoul(argv[2], 0, 0); 267*d6b92ffaSHans Petter Selasky 268*d6b92ffaSHans Petter Selasky if (umad_init() < 0) 269*d6b92ffaSHans Petter Selasky IBPANIC("can't init UMAD library"); 270*d6b92ffaSHans Petter Selasky 271*d6b92ffaSHans Petter Selasky if ((portid = umad_open_port(ibd_ca, ibd_ca_port)) < 0) 272*d6b92ffaSHans Petter Selasky IBPANIC("can't open UMAD port (%s:%d)", ibd_ca, ibd_ca_port); 273*d6b92ffaSHans Petter Selasky 274*d6b92ffaSHans Petter Selasky if ((mad_agent = umad_register(portid, mgmt_class, 1, 0, 0)) < 0) 275*d6b92ffaSHans Petter Selasky IBPANIC("Couldn't register agent for SMPs"); 276*d6b92ffaSHans Petter Selasky 277*d6b92ffaSHans Petter Selasky if (!(umad = umad_alloc(1, umad_size() + IB_MAD_SIZE))) 278*d6b92ffaSHans Petter Selasky IBPANIC("can't alloc MAD"); 279*d6b92ffaSHans Petter Selasky 280*d6b92ffaSHans Petter Selasky smp = umad_get_mad(umad); 281*d6b92ffaSHans Petter Selasky 282*d6b92ffaSHans Petter Selasky if (mgmt_class == IB_SMI_DIRECT_CLASS) 283*d6b92ffaSHans Petter Selasky drsmp_get_init(umad, &path, attr, mod); 284*d6b92ffaSHans Petter Selasky else 285*d6b92ffaSHans Petter Selasky smp_get_init(umad, dlid, attr, mod); 286*d6b92ffaSHans Petter Selasky 287*d6b92ffaSHans Petter Selasky if (ibdebug > 1) 288*d6b92ffaSHans Petter Selasky xdump(stderr, "before send:\n", smp, 256); 289*d6b92ffaSHans Petter Selasky 290*d6b92ffaSHans Petter Selasky length = IB_MAD_SIZE; 291*d6b92ffaSHans Petter Selasky if (umad_send(portid, mad_agent, umad, length, ibd_timeout, 0) < 0) 292*d6b92ffaSHans Petter Selasky IBPANIC("send failed"); 293*d6b92ffaSHans Petter Selasky 294*d6b92ffaSHans Petter Selasky if (umad_recv(portid, umad, &length, -1) != mad_agent) 295*d6b92ffaSHans Petter Selasky IBPANIC("recv error: %s", drmad_status_str(smp)); 296*d6b92ffaSHans Petter Selasky 297*d6b92ffaSHans Petter Selasky if (!dump_char) { 298*d6b92ffaSHans Petter Selasky xdump(stdout, 0, smp->data, 64); 299*d6b92ffaSHans Petter Selasky if (smp->status) 300*d6b92ffaSHans Petter Selasky fprintf(stdout, "SMP status: 0x%x\n", 301*d6b92ffaSHans Petter Selasky ntohs(smp->status)); 302*d6b92ffaSHans Petter Selasky goto exit; 303*d6b92ffaSHans Petter Selasky } 304*d6b92ffaSHans Petter Selasky 305*d6b92ffaSHans Petter Selasky desc = smp->data; 306*d6b92ffaSHans Petter Selasky for (i = 0; i < 64; ++i) { 307*d6b92ffaSHans Petter Selasky if (!desc[i]) 308*d6b92ffaSHans Petter Selasky break; 309*d6b92ffaSHans Petter Selasky putchar(desc[i]); 310*d6b92ffaSHans Petter Selasky } 311*d6b92ffaSHans Petter Selasky putchar('\n'); 312*d6b92ffaSHans Petter Selasky if (smp->status) 313*d6b92ffaSHans Petter Selasky fprintf(stdout, "SMP status: 0x%x\n", ntohs(smp->status)); 314*d6b92ffaSHans Petter Selasky 315*d6b92ffaSHans Petter Selasky exit: 316*d6b92ffaSHans Petter Selasky umad_free(umad); 317*d6b92ffaSHans Petter Selasky return 0; 318*d6b92ffaSHans Petter Selasky } 319