]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/ofed/management/infiniband-diags/src/ibsysstat.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / ofed / management / infiniband-diags / src / ibsysstat.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 #if HAVE_CONFIG_H
35 #  include <config.h>
36 #endif /* HAVE_CONFIG_H */
37
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <unistd.h>
41 #include <stdarg.h>
42 #include <time.h>
43 #include <string.h>
44 #include <getopt.h>
45
46 #include <infiniband/common.h>
47 #include <infiniband/umad.h>
48 #include <infiniband/mad.h>
49
50 #include "ibdiag_common.h"
51
52 #undef DEBUG
53 #define DEBUG   if (verbose) IBWARN
54
55 static int dest_type = IB_DEST_LID;
56 static int verbose;
57
58 #define MAX_CPUS 8
59
60 enum ib_sysstat_attr_t {
61         IB_PING_ATTR = 0x10,
62         IB_HOSTINFO_ATTR = 0x11,
63         IB_CPUINFO_ATTR = 0x12,
64 };
65
66 typedef struct cpu_info {
67         char *model;
68         char *mhz;
69 } cpu_info;
70
71 static cpu_info cpus[MAX_CPUS];
72 static int host_ncpu;
73
74 char *argv0 = "ibsysstat";
75
76 static void
77 mk_reply(int attr, void *data, int sz)
78 {
79         char *s = data;
80         int n, i;
81
82         switch (attr) {
83         case IB_PING_ATTR:
84                 break;          /* nothing to do here, just reply */
85         case IB_HOSTINFO_ATTR:
86                 if (gethostname(s, sz) < 0)
87                         snprintf(s, sz, "?hostname?");
88                 s[sz-1] = 0;
89                 if ((n = strlen(s)) >= sz)
90                         break;
91                 s[n] = '.';
92                 s += n+1;
93                 sz -= n+1;
94                 if (getdomainname(s, sz) < 0)
95                         snprintf(s, sz, "?domainname?");
96                 if (strlen(s) == 0)
97                         s[-1] = 0;      /* no domain */
98                 break;
99         case IB_CPUINFO_ATTR:
100                 for (i = 0; i < host_ncpu && sz > 0; i++) {
101                         n = snprintf(s, sz, "cpu %d: model %s MHZ %s\n",
102                                      i, cpus[i].model, cpus[i].mhz);
103                         if (n >= sz) {
104                                 IBWARN("cpuinfo truncated");
105                                 break;
106                         }
107                         sz -= n;
108                         s += n;
109                 }
110                 break;
111         default:
112                 DEBUG("unknown attr %d", attr);
113         }
114 }
115
116 static char *
117 ibsystat_serv(void)
118 {
119         void *umad;
120         void *mad;
121         int attr, mod;
122
123         DEBUG("starting to serve...");
124
125         while ((umad = mad_receive(0, -1))) {
126
127                 mad = umad_get_mad(umad);
128
129                 attr = mad_get_field(mad, 0, IB_MAD_ATTRID_F);
130                 mod = mad_get_field(mad, 0, IB_MAD_ATTRMOD_F);
131
132                 DEBUG("got packet: attr 0x%x mod 0x%x", attr, mod);
133
134                 mk_reply(attr, (char *)mad + IB_VENDOR_RANGE2_DATA_OFFS, IB_VENDOR_RANGE2_DATA_SIZE);
135
136                 if (mad_respond(umad, 0, 0) < 0)
137                         DEBUG("respond failed");
138
139                 mad_free(umad);
140         }
141
142         DEBUG("server out");
143         return 0;
144 }
145
146 static int
147 match_attr(char *str)
148 {
149         if (!strcmp(str, "ping"))
150                 return IB_PING_ATTR;
151         if (!strcmp(str, "host"))
152                 return IB_HOSTINFO_ATTR;
153         if (!strcmp(str, "cpu"))
154                 return IB_CPUINFO_ATTR;
155         return -1;
156 }
157
158 static char *
159 ibsystat(ib_portid_t *portid, int attr)
160 {
161         char data[IB_VENDOR_RANGE2_DATA_SIZE] = {0};
162         ib_vendor_call_t call;
163
164         DEBUG("Sysstat ping..");
165
166         call.method = IB_MAD_METHOD_GET;
167         call.mgmt_class = IB_VENDOR_OPENIB_SYSSTAT_CLASS;
168         call.attrid = attr;
169         call.mod = 0;
170         call.oui = IB_OPENIB_OUI;
171         call.timeout = 0;
172         memset(&call.rmpp, 0, sizeof call.rmpp);
173
174         if (!ib_vendor_call(data, portid, &call))
175                 return "vendor call failed";
176
177         DEBUG("Got sysstat pong..");
178         if (attr != IB_PING_ATTR)
179                 puts(data);
180         else
181                 printf("sysstat ping succeeded\n");
182         return 0;
183 }
184
185 int
186 build_cpuinfo(void)
187 {
188         char line[1024] = {0}, *s, *e;
189         FILE *f;
190         int ncpu = 0;
191
192         if (!(f = fopen("/proc/cpuinfo", "r"))) {
193                 IBWARN("couldn't open /proc/cpuinfo");
194                 return 0;
195         }
196
197         while (fgets(line, sizeof(line) - 1, f)) {
198                 if (!strncmp(line, "processor\t", 10)) {
199                         ncpu++;
200                         if (ncpu > MAX_CPUS)
201                                 return MAX_CPUS;
202                         continue;
203                 }
204
205                 if (!ncpu || !(s = strchr(line, ':')))
206                         continue;
207
208                 if ((e = strchr(s, '\n')))
209                         *e = 0;
210                 if (!strncmp(line, "model name\t", 11))
211                         cpus[ncpu-1].model = strdup(s+1);
212                 else if (!strncmp(line, "cpu MHz\t", 8))
213                         cpus[ncpu-1].mhz = strdup(s+1);
214         }
215
216         fclose(f);
217
218         DEBUG("ncpu %d", ncpu);
219
220         return ncpu;
221 }
222
223 static void
224 usage(void)
225 {
226         char *basename;
227
228         if (!(basename = strrchr(argv0, '/')))
229                 basename = argv0;
230         else
231                 basename++;
232
233         fprintf(stderr, "Usage: %s [-d(ebug) -e(rr_show) -v(erbose) -G(uid) -s smlid -V(ersion) -C ca_name -P ca_port "
234                         "-t(imeout) timeout_ms -o oui -S(erver)] <dest lid|guid> [<op>]\n",
235                         basename);
236         exit(-1);
237 }
238
239 int
240 main(int argc, char **argv)
241 {
242         int mgmt_classes[3] = {IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS};
243         int sysstat_class = IB_VENDOR_OPENIB_SYSSTAT_CLASS;
244         ib_portid_t portid = {0};
245         ib_portid_t *sm_id = 0, sm_portid = {0};
246         int timeout = 0, udebug = 0, server = 0;
247         int oui = IB_OPENIB_OUI, attr = IB_PING_ATTR;
248         extern int ibdebug;
249         char *err;
250         char *ca = 0;
251         int ca_port = 0;
252
253         static char const str_opts[] = "C:P:t:s:o:devGSVhu";
254         static const struct option long_opts[] = {
255                 { "C", 1, 0, 'C'},
256                 { "P", 1, 0, 'P'},
257                 { "debug", 0, 0, 'd'},
258                 { "err_show", 0, 0, 'e'},
259                 { "verbose", 0, 0, 'v'},
260                 { "Guid", 0, 0, 'G'},
261                 { "timeout", 1, 0, 't'},
262                 { "s", 1, 0, 's'},
263                 { "o", 1, 0, 'o'},
264                 { "Server", 0, 0, 'S'},
265                 { "Version", 0, 0, 'V'},
266                 { "help", 0, 0, 'h'},
267                 { "usage", 0, 0, 'u'},
268                 { }
269         };
270
271         argv0 = argv[0];
272
273         while (1) {
274                 int ch = getopt_long(argc, argv, str_opts, long_opts, NULL);
275                 if ( ch == -1 )
276                         break;
277                 switch(ch) {
278                 case 'C':
279                         ca = optarg;
280                         break;
281                 case 'P':
282                         ca_port = strtoul(optarg, 0, 0);
283                         break;
284                 case 'd':
285                         ibdebug++;
286                         madrpc_show_errors(1);
287                         umad_debug(udebug);
288                         udebug++;
289                         break;
290                 case 'e':
291                         madrpc_show_errors(1);
292                         break;
293                 case 'G':
294                         dest_type = IB_DEST_GUID;
295                         break;
296                 case 'o':
297                         oui = strtoul(optarg, 0, 0);
298                         break;
299                 case 's':
300                         if (ib_resolve_portid_str(&sm_portid, optarg, IB_DEST_LID, 0) < 0)
301                                 IBERROR("can't resolve SM destination port %s", optarg);
302                         sm_id = &sm_portid;
303                         break;
304                 case 'S':
305                         server++;
306                         break;
307                 case 't':
308                         timeout = strtoul(optarg, 0, 0);
309                         madrpc_set_timeout(timeout);
310                         break;
311                 case 'v':
312                         verbose++;
313                         break;
314                 case 'V':
315                         fprintf(stderr, "%s %s\n", argv0, get_build_version() );
316                         exit(-1);
317                 default:
318                         usage();
319                         break;
320                 }
321         }
322         argc -= optind;
323         argv += optind;
324
325         if (!argc && !server)
326                 usage();
327
328         if (argc > 1 && (attr = match_attr(argv[1])) < 0)
329                 usage();
330
331         madrpc_init(ca, ca_port, mgmt_classes, 3);
332
333         if (server) {
334                 if (mad_register_server(sysstat_class, 0, 0, oui) < 0)
335                         IBERROR("can't serve class %d", sysstat_class);
336
337                 host_ncpu = build_cpuinfo();
338
339                 if ((err = ibsystat_serv()))
340                         IBERROR("ibssystat to %s: %s", portid2str(&portid), err);
341                 exit(0);
342         }
343
344         if (mad_register_client(sysstat_class, 0) < 0)
345                 IBERROR("can't register to sysstat class %d", sysstat_class);
346
347         if (ib_resolve_portid_str(&portid, argv[0], dest_type, sm_id) < 0)
348                 IBERROR("can't resolve destination port %s", argv[0]);
349
350         if ((err = ibsystat(&portid, attr)))
351                 IBERROR("ibsystat to %s: %s", portid2str(&portid), err);
352
353         exit(0);
354 }