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