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