1219820Sjeff/*
2219820Sjeff * Copyright (c) 2008 Lawrence Livermore National Security
3219820Sjeff *
4219820Sjeff * Produced at Lawrence Livermore National Laboratory.
5219820Sjeff * Written by Ira Weiny <weiny2@llnl.gov>.
6219820Sjeff *
7219820Sjeff * This software is available to you under a choice of one of two
8219820Sjeff * licenses.  You may choose to be licensed under the terms of the GNU
9219820Sjeff * General Public License (GPL) Version 2, available from the file
10219820Sjeff * COPYING in the main directory of this source tree, or the
11219820Sjeff * OpenIB.org BSD license below:
12219820Sjeff *
13219820Sjeff *     Redistribution and use in source and binary forms, with or
14219820Sjeff *     without modification, are permitted provided that the following
15219820Sjeff *     conditions are met:
16219820Sjeff *
17219820Sjeff *      - Redistributions of source code must retain the above
18219820Sjeff *        copyright notice, this list of conditions and the following
19219820Sjeff *        disclaimer.
20219820Sjeff *
21219820Sjeff *      - Redistributions in binary form must reproduce the above
22219820Sjeff *        copyright notice, this list of conditions and the following
23219820Sjeff *        disclaimer in the documentation and/or other materials
24219820Sjeff *        provided with the distribution.
25219820Sjeff *
26219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
30219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
31219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
32219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33219820Sjeff * SOFTWARE.
34219820Sjeff *
35219820Sjeff */
36219820Sjeff
37219820Sjeff#include <stdlib.h>
38219820Sjeff#include <stdio.h>
39219820Sjeff#include <unistd.h>
40219820Sjeff#include <string.h>
41219820Sjeff
42219820Sjeff#define _GNU_SOURCE
43219820Sjeff#include <getopt.h>
44219820Sjeff
45219820Sjeff#include <infiniband/mad.h>
46219820Sjeff#include <infiniband/iba/ib_types.h>
47219820Sjeff
48219820Sjeff#include "ibdiag_common.h"
49219820Sjeff
50219820Sjeffchar *argv0 = "";
51219820Sjeff
52219820Sjeffstatic int send_144_node_desc_update(void)
53219820Sjeff{
54219820Sjeff	ib_portid_t sm_port;
55219820Sjeff	ib_portid_t selfportid;
56219820Sjeff	int selfport;
57219820Sjeff	ib_rpc_t trap_rpc;
58219820Sjeff	ib_mad_notice_attr_t notice;
59219820Sjeff
60219820Sjeff	if (ib_resolve_self(&selfportid, &selfport, NULL))
61219820Sjeff		IBERROR("can't resolve self");
62219820Sjeff
63219820Sjeff	if (ib_resolve_smlid(&sm_port, 0))
64219820Sjeff		IBERROR("can't resolve SM destination port");
65219820Sjeff
66219820Sjeff	memset(&trap_rpc, 0, sizeof(trap_rpc));
67219820Sjeff	trap_rpc.mgtclass = IB_SMI_CLASS;
68219820Sjeff	trap_rpc.method = IB_MAD_METHOD_TRAP;
69219820Sjeff	trap_rpc.trid = mad_trid();
70219820Sjeff	trap_rpc.attr.id = NOTICE;
71219820Sjeff	trap_rpc.datasz = IB_SMP_DATA_SIZE;
72219820Sjeff	trap_rpc.dataoffs = IB_SMP_DATA_OFFS;
73219820Sjeff
74219820Sjeff	memset(&notice, 0, sizeof(notice));
75219820Sjeff	notice.generic_type = 0x80 | IB_NOTICE_TYPE_INFO;
76219820Sjeff	notice.g_or_v.generic.prod_type_lsb = cl_hton16(IB_NODE_TYPE_CA);
77219820Sjeff	notice.g_or_v.generic.trap_num = cl_hton16(144);
78219820Sjeff	notice.issuer_lid = cl_hton16(selfportid.lid);
79219820Sjeff	notice.data_details.ntc_144.lid = cl_hton16(selfportid.lid);
80219820Sjeff	notice.data_details.ntc_144.local_changes =
81219820Sjeff	    TRAP_144_MASK_OTHER_LOCAL_CHANGES;
82219820Sjeff	notice.data_details.ntc_144.change_flgs =
83219820Sjeff	    TRAP_144_MASK_NODE_DESCRIPTION_CHANGE;
84219820Sjeff
85219820Sjeff	return (mad_send(&trap_rpc, &sm_port, NULL, &notice));
86219820Sjeff}
87219820Sjeff
88219820Sjefftypedef struct _trap_def {
89219820Sjeff	char *trap_name;
90219820Sjeff	int (*send_func) (void);
91219820Sjeff} trap_def_t;
92219820Sjeff
93219820Sjefftrap_def_t traps[2] = {
94219820Sjeff	{"node_desc_change", send_144_node_desc_update},
95219820Sjeff	{NULL, NULL}
96219820Sjeff};
97219820Sjeff
98219820Sjeffstatic void usage(void)
99219820Sjeff{
100219820Sjeff	int i;
101219820Sjeff
102219820Sjeff	fprintf(stderr, "Usage: %s [-hV]"
103219820Sjeff		" [-C <ca_name>] [-P <ca_port>] [<trap_name>]\n", argv0);
104219820Sjeff	fprintf(stderr, "   -V print version\n");
105219820Sjeff	fprintf(stderr, "   <trap_name> can be one of the following\n");
106219820Sjeff	for (i = 0; traps[i].trap_name; i++) {
107219820Sjeff		fprintf(stderr, "      %s\n", traps[i].trap_name);
108219820Sjeff	}
109219820Sjeff	fprintf(stderr, "   default behavior is to send \"%s\"\n",
110219820Sjeff		traps[0].trap_name);
111219820Sjeff
112219820Sjeff	exit(-1);
113219820Sjeff}
114219820Sjeff
115219820Sjeffint send_trap(char *trap_name)
116219820Sjeff{
117219820Sjeff	int i;
118219820Sjeff
119219820Sjeff	for (i = 0; traps[i].trap_name; i++) {
120219820Sjeff		if (strcmp(traps[i].trap_name, trap_name) == 0) {
121219820Sjeff			return (traps[i].send_func());
122219820Sjeff		}
123219820Sjeff	}
124219820Sjeff	usage();
125219820Sjeff	exit(1);
126219820Sjeff}
127219820Sjeff
128219820Sjeffint main(int argc, char **argv)
129219820Sjeff{
130219820Sjeff	int mgmt_classes[2] = { IB_SMI_CLASS, IB_SMI_DIRECT_CLASS };
131219820Sjeff	int ch = 0;
132219820Sjeff	char *trap_name = NULL;
133219820Sjeff	char *ca = NULL;
134219820Sjeff	int ca_port = 0;
135219820Sjeff
136219820Sjeff	static char const str_opts[] = "hVP:C:";
137219820Sjeff	static const struct option long_opts[] = {
138219820Sjeff		{"Version", 0, 0, 'V'},
139219820Sjeff		{"P", 1, 0, 'P'},
140219820Sjeff		{"C", 1, 0, 'C'},
141219820Sjeff		{"help", 0, 0, 'h'},
142219820Sjeff		{}
143219820Sjeff	};
144219820Sjeff
145219820Sjeff	argv0 = argv[0];
146219820Sjeff
147219820Sjeff	while ((ch = getopt_long(argc, argv, str_opts, long_opts, NULL)) != -1) {
148219820Sjeff		switch (ch) {
149219820Sjeff		case 'V':
150219820Sjeff			fprintf(stderr, "%s %s\n", argv0, get_build_version());
151219820Sjeff			exit(-1);
152219820Sjeff		case 'C':
153219820Sjeff			ca = optarg;
154219820Sjeff			break;
155219820Sjeff		case 'P':
156219820Sjeff			ca_port = strtoul(optarg, NULL, 0);
157219820Sjeff			break;
158219820Sjeff		case 'h':
159219820Sjeff		default:
160219820Sjeff			usage();
161219820Sjeff		}
162219820Sjeff	}
163219820Sjeff	argc -= optind;
164219820Sjeff	argv += optind;
165219820Sjeff
166219820Sjeff	if (!argv[0]) {
167219820Sjeff		trap_name = traps[0].trap_name;
168219820Sjeff	} else {
169219820Sjeff		trap_name = argv[0];
170219820Sjeff	}
171219820Sjeff
172219820Sjeff	madrpc_show_errors(1);
173219820Sjeff	madrpc_init(ca, ca_port, mgmt_classes, 2);
174219820Sjeff
175219820Sjeff	return (send_trap(trap_name));
176219820Sjeff}
177