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