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