]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/ofed/management/infiniband-diags/src/smpdump.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / ofed / management / infiniband-diags / src / smpdump.c
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
65 static const uint8_t  CLASS_SUBN_DIRECTED_ROUTE = 0x81;
66 static 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
72 static int mad_agent;
73 static int drmad_tid = 0x123;
74
75 static int debug, verbose;
76
77 char *argv0 = "smpdump";
78
79 typedef struct {
80         char path[64];
81         int hop_cnt;
82 } DRPath;
83
84 struct 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
105 void
106 drsmp_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
131 void
132 smp_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
150 void
151 drsmp_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
175 char *
176 drmad_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
187 int
188 str2DRPath(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
215 void
216 usage(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
229 int
230 main(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 }