]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/ofed/infiniband-diags/src/ibsysstat.c
MFV r361280:
[FreeBSD/FreeBSD.git] / contrib / ofed / infiniband-diags / src / ibsysstat.c
1 /*
2  * Copyright (c) 2004-2009 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 <string.h>
42 #include <getopt.h>
43
44 #include <infiniband/umad.h>
45 #include <infiniband/mad.h>
46
47 #include <sys/sysctl.h>
48
49 #include "ibdiag_common.h"
50
51 #define MAX_CPUS 8
52
53 struct ibmad_port *srcport;
54
55 static ibmad_gid_t dgid;
56 static int with_grh;
57
58 enum ib_sysstat_attr_t {
59         IB_PING_ATTR = 0x10,
60         IB_HOSTINFO_ATTR = 0x11,
61         IB_CPUINFO_ATTR = 0x12,
62 };
63
64 typedef struct cpu_info {
65         char *model;
66         char *mhz;
67 } cpu_info;
68
69 static cpu_info cpus[MAX_CPUS];
70 static int host_ncpu;
71 static int server = 0, oui = IB_OPENIB_OUI;
72
73 static int server_respond(void *umad, int size)
74 {
75         ib_rpc_t rpc = { 0 };
76         ib_rmpp_hdr_t rmpp = { 0 };
77         ib_portid_t rport;
78         uint8_t *mad = umad_get_mad(umad);
79         ib_mad_addr_t *mad_addr;
80
81         if (!(mad_addr = umad_get_mad_addr(umad)))
82                 return -1;
83
84         memset(&rport, 0, sizeof(rport));
85
86         rport.lid = ntohs(mad_addr->lid);
87         rport.qp = ntohl(mad_addr->qpn);
88         rport.qkey = ntohl(mad_addr->qkey);
89         rport.sl = mad_addr->sl;
90         if (!rport.qkey && rport.qp == 1)
91                 rport.qkey = IB_DEFAULT_QP1_QKEY;
92         rport.grh_present = mad_addr->grh_present;
93         if (rport.grh_present)
94                 memcpy(rport.gid, mad_addr->gid, 16);
95
96         rpc.mgtclass = mad_get_field(mad, 0, IB_MAD_MGMTCLASS_F);
97         rpc.method = IB_MAD_METHOD_GET | IB_MAD_RESPONSE;
98         rpc.attr.id = mad_get_field(mad, 0, IB_MAD_ATTRID_F);
99         rpc.attr.mod = mad_get_field(mad, 0, IB_MAD_ATTRMOD_F);
100         rpc.oui = mad_get_field(mad, 0, IB_VEND2_OUI_F);
101         rpc.trid = mad_get_field64(mad, 0, IB_MAD_TRID_F);
102
103         if (size > IB_MAD_SIZE)
104                 rmpp.flags = IB_RMPP_FLAG_ACTIVE;
105
106         DEBUG("responding %d bytes to %s, attr 0x%x mod 0x%x qkey %x",
107               size, portid2str(&rport), rpc.attr.id, rpc.attr.mod, rport.qkey);
108
109         if (mad_build_pkt(umad, &rpc, &rport, &rmpp, 0) < 0)
110                 return -1;
111
112         if (ibdebug > 1)
113                 xdump(stderr, "mad respond pkt\n", mad, IB_MAD_SIZE);
114
115         if (umad_send(mad_rpc_portid(srcport),
116                       mad_rpc_class_agent(srcport, rpc.mgtclass), umad, size,
117                       rpc.timeout, 0) < 0) {
118                 DEBUG("send failed; %m");
119                 return -1;
120         }
121
122         return 0;
123 }
124
125 static int mk_reply(int attr, void *data, int sz)
126 {
127         char *s = data;
128         int n, i, ret = 0;
129
130         switch (attr) {
131         case IB_PING_ATTR:
132                 break;          /* nothing to do here, just reply */
133         case IB_HOSTINFO_ATTR:
134                 if (gethostname(s, sz) < 0)
135                         snprintf(s, sz, "?hostname?");
136                 s[sz - 1] = 0;
137                 if ((n = strlen(s)) >= sz - 1) {
138                         ret = sz;
139                         break;
140                 }
141                 s[n] = '.';
142                 s += n + 1;
143                 sz -= n + 1;
144                 ret += n + 1;
145                 if (getdomainname(s, sz) < 0)
146                         snprintf(s, sz, "?domainname?");
147                 if ((n = strlen(s)) == 0)
148                         s[-1] = 0;      /* no domain */
149                 else
150                         ret += n;
151                 break;
152         case IB_CPUINFO_ATTR:
153                 s[0] = '\0';
154                 for (i = 0; i < host_ncpu && sz > 0; i++) {
155                         n = snprintf(s, sz, "cpu %d: model %s MHZ %s\n",
156                                      i, cpus[i].model, cpus[i].mhz);
157                         if (n >= sz) {
158                                 IBWARN("cpuinfo truncated");
159                                 ret = sz;
160                                 break;
161                         }
162                         sz -= n;
163                         s += n;
164                         ret += n;
165                 }
166                 ret++;
167                 break;
168         default:
169                 DEBUG("unknown attr %d", attr);
170         }
171         return ret;
172 }
173
174 static uint8_t buf[2048];
175
176 static char *ibsystat_serv(void)
177 {
178         void *umad;
179         void *mad;
180         int attr, mod, size;
181
182         DEBUG("starting to serve...");
183
184         while ((umad = mad_receive_via(buf, -1, srcport))) {
185                 if (umad_status(buf)) {
186                         DEBUG("drop mad with status %x: %s", umad_status(buf),
187                               strerror(umad_status(buf)));
188                         continue;
189                 }
190
191                 mad = umad_get_mad(umad);
192
193                 attr = mad_get_field(mad, 0, IB_MAD_ATTRID_F);
194                 mod = mad_get_field(mad, 0, IB_MAD_ATTRMOD_F);
195
196                 DEBUG("got packet: attr 0x%x mod 0x%x", attr, mod);
197
198                 size =
199                     mk_reply(attr, (uint8_t *) mad + IB_VENDOR_RANGE2_DATA_OFFS,
200                              sizeof(buf) - umad_size() -
201                              IB_VENDOR_RANGE2_DATA_OFFS);
202
203                 if (server_respond(umad, IB_VENDOR_RANGE2_DATA_OFFS + size) < 0)
204                         DEBUG("respond failed");
205         }
206
207         DEBUG("server out");
208         return 0;
209 }
210
211 static int match_attr(char *str)
212 {
213         if (!strcmp(str, "ping"))
214                 return IB_PING_ATTR;
215         if (!strcmp(str, "host"))
216                 return IB_HOSTINFO_ATTR;
217         if (!strcmp(str, "cpu"))
218                 return IB_CPUINFO_ATTR;
219         return -1;
220 }
221
222 static char *ibsystat(ib_portid_t * portid, int attr)
223 {
224         ib_rpc_t rpc = { 0 };
225         int fd, agent, timeout, len;
226         void *data = (uint8_t *) umad_get_mad(buf) + IB_VENDOR_RANGE2_DATA_OFFS;
227
228         DEBUG("Sysstat ping..");
229
230         rpc.mgtclass = IB_VENDOR_OPENIB_SYSSTAT_CLASS;
231         rpc.method = IB_MAD_METHOD_GET;
232         rpc.attr.id = attr;
233         rpc.attr.mod = 0;
234         rpc.oui = oui;
235         rpc.timeout = 0;
236         rpc.datasz = IB_VENDOR_RANGE2_DATA_SIZE;
237         rpc.dataoffs = IB_VENDOR_RANGE2_DATA_OFFS;
238
239         portid->qp = 1;
240         if (!portid->qkey)
241                 portid->qkey = IB_DEFAULT_QP1_QKEY;
242
243         if ((len = mad_build_pkt(buf, &rpc, portid, NULL, NULL)) < 0)
244                 IBPANIC("cannot build packet.");
245
246         fd = mad_rpc_portid(srcport);
247         agent = mad_rpc_class_agent(srcport, rpc.mgtclass);
248         timeout = ibd_timeout ? ibd_timeout : MAD_DEF_TIMEOUT_MS;
249
250         if (umad_send(fd, agent, buf, len, timeout, 0) < 0)
251                 IBPANIC("umad_send failed.");
252
253         len = sizeof(buf) - umad_size();
254         if (umad_recv(fd, buf, &len, timeout) < 0)
255                 IBPANIC("umad_recv failed.");
256
257         if (umad_status(buf))
258                 return strerror(umad_status(buf));
259
260         DEBUG("Got sysstat pong..");
261         if (attr != IB_PING_ATTR)
262                 puts(data);
263         else
264                 printf("sysstat ping succeeded\n");
265         return 0;
266 }
267
268 int build_cpuinfo(void)
269 {
270         int ret;
271         size_t size = sizeof(ret);
272
273         if (sysctlbyname("hw.ncpu", &ret, &size, NULL, 0) != 0 || ret < 1)
274                 ret = 1;
275         return ret;
276
277         DEBUG("ncpu %d", ret);
278 }
279
280 static int process_opt(void *context, int ch, char *optarg)
281 {
282         switch (ch) {
283         case 'o':
284                 oui = strtoul(optarg, 0, 0);
285                 break;
286         case 'S':
287                 server++;
288                 break;
289         case 25:
290                 if (!inet_pton(AF_INET6, optarg, &dgid)) {
291                         fprintf(stderr, "dgid format is wrong!\n");
292                         ibdiag_show_usage();
293                         return 1;
294                 }
295                 with_grh = 1;
296                 break;
297         default:
298                 return -1;
299         }
300         return 0;
301 }
302
303 int main(int argc, char **argv)
304 {
305         int mgmt_classes[3] =
306             { IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS };
307         int sysstat_class = IB_VENDOR_OPENIB_SYSSTAT_CLASS;
308         ib_portid_t portid = { 0 };
309         int attr = IB_PING_ATTR;
310         char *err;
311
312         const struct ibdiag_opt opts[] = {
313                 {"oui", 'o', 1, NULL, "use specified OUI number"},
314                 {"Server", 'S', 0, NULL, "start in server mode"},
315                 {"dgid", 25, 1, NULL, "remote gid (IPv6 format)"},
316                 {0}
317         };
318         char usage_args[] = "<dest lid|guid> [<op>]";
319
320         ibdiag_process_opts(argc, argv, NULL, "DKy", opts, process_opt,
321                             usage_args, NULL);
322
323         argc -= optind;
324         argv += optind;
325
326         if (!argc && !server)
327                 ibdiag_show_usage();
328
329         if (argc > 1 && (attr = match_attr(argv[1])) < 0)
330                 ibdiag_show_usage();
331
332         srcport = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 3);
333         if (!srcport)
334                 IBEXIT("Failed to open '%s' port '%d'", ibd_ca, ibd_ca_port);
335
336         if (server) {
337                 if (mad_register_server_via(sysstat_class, 1, 0, oui, srcport) <
338                     0)
339                         IBEXIT("can't serve class %d", sysstat_class);
340
341                 host_ncpu = build_cpuinfo();
342
343                 if ((err = ibsystat_serv()))
344                         IBEXIT("ibssystat to %s: %s", portid2str(&portid),
345                                 err);
346                 exit(0);
347         }
348
349         if (mad_register_client_via(sysstat_class, 1, srcport) < 0)
350                 IBEXIT("can't register to sysstat class %d", sysstat_class);
351
352         if (with_grh && ibd_dest_type != IB_DEST_LID)
353                 IBEXIT("When using GRH, LID should be provided");
354         if (resolve_portid_str(ibd_ca, ibd_ca_port, &portid, argv[0],
355                                ibd_dest_type, ibd_sm_id, srcport) < 0)
356                 IBEXIT("can't resolve destination port %s", argv[0]);
357         if (with_grh) {
358                 portid.grh_present = 1;
359                 memcpy(&portid.gid, &dgid, sizeof(portid.gid));
360         }
361
362         if ((err = ibsystat(&portid, attr)))
363                 IBEXIT("ibsystat to %s: %s", portid2str(&portid), err);
364
365         mad_rpc_close_port(srcport);
366         exit(0);
367 }