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
drsmp_get_init(void * umad,DRPath * path,int attr,int mod)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
smp_get_init(void * umad,int lid,int attr,int mod)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
drsmp_set_init(void * umad,DRPath * path,int attr,int mod,void * data)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
drmad_status_str(struct drsmp * drsmp)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
str2DRPath(char * str,DRPath * path)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
process_opt(void * context,int ch,char * optarg)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
main(int argc,char * argv[])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