]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/ofed/management/infiniband-diags/src/perfquery.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / contrib / ofed / management / infiniband-diags / src / perfquery.c
1 /*
2  * Copyright (c) 2004-2008 Voltaire Inc.  All rights reserved.
3  * Copyright (c) 2007 Xsigo Systems Inc.  All rights reserved.
4  *
5  * This software is available to you under a choice of one of two
6  * licenses.  You may choose to be licensed under the terms of the GNU
7  * General Public License (GPL) Version 2, available from the file
8  * COPYING in the main directory of this source tree, or the
9  * OpenIB.org BSD license below:
10  *
11  *     Redistribution and use in source and binary forms, with or
12  *     without modification, are permitted provided that the following
13  *     conditions are met:
14  *
15  *      - Redistributions of source code must retain the above
16  *        copyright notice, this list of conditions and the following
17  *        disclaimer.
18  *
19  *      - Redistributions in binary form must reproduce the above
20  *        copyright notice, this list of conditions and the following
21  *        disclaimer in the documentation and/or other materials
22  *        provided with the distribution.
23  *
24  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31  * SOFTWARE.
32  *
33  */
34
35 #if HAVE_CONFIG_H
36 #  include <config.h>
37 #endif /* HAVE_CONFIG_H */
38
39 #include <stdio.h>
40 #include <stdlib.h>
41 #include <unistd.h>
42 #include <stdarg.h>
43 #include <getopt.h>
44 #include <netinet/in.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 struct perf_count {
53         uint32_t portselect;
54         uint32_t counterselect;
55         uint32_t symbolerrors;
56         uint32_t linkrecovers;
57         uint32_t linkdowned;
58         uint32_t rcverrors;
59         uint32_t rcvremotephyerrors;
60         uint32_t rcvswrelayerrors;
61         uint32_t xmtdiscards;
62         uint32_t xmtconstrainterrors;
63         uint32_t rcvconstrainterrors;
64         uint32_t linkintegrityerrors;
65         uint32_t excbufoverrunerrors;
66         uint32_t vl15dropped;
67         uint32_t xmtdata;
68         uint32_t rcvdata;
69         uint32_t xmtpkts;
70         uint32_t rcvpkts;
71 };
72
73 struct perf_count_ext {
74         uint32_t portselect;
75         uint32_t counterselect;
76         uint64_t portxmitdata;
77         uint64_t portrcvdata;
78         uint64_t portxmitpkts;
79         uint64_t portrcvpkts;
80         uint64_t portunicastxmitpkts;
81         uint64_t portunicastrcvpkts;
82         uint64_t portmulticastxmitpkits;
83         uint64_t portmulticastrcvpkts;
84 };
85
86 static uint8_t pc[1024];
87
88 struct perf_count perf_count = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
89 struct perf_count_ext perf_count_ext = {0,0,0,0,0,0,0,0,0,0};
90
91 char *argv0 = "perfquery";
92
93 #define ALL_PORTS 0xFF
94
95 static void
96 usage(void)
97 {
98         char *basename;
99
100         if (!(basename = strrchr(argv0, '/')))
101                 basename = argv0;
102         else
103                 basename++;
104
105         fprintf(stderr, "Usage: %s [-d(ebug) -G(uid) -a(ll_ports) -l(oop_ports) -r(eset_after_read) -C ca_name -P ca_port "
106                         "-R(eset_only) -t(imeout) timeout_ms -V(ersion) -h(elp)] [<lid|guid> [[port] [reset_mask]]]\n",
107                         basename);
108         fprintf(stderr, "\tExamples:\n");
109         fprintf(stderr, "\t\t%s\t\t# read local port's performance counters\n", basename);
110         fprintf(stderr, "\t\t%s 32 1\t\t# read performance counters from lid 32, port 1\n", basename);
111         fprintf(stderr, "\t\t%s -e 32 1\t# read extended performance counters from lid 32, port 1\n", basename);
112         fprintf(stderr, "\t\t%s -a 32\t\t# read performance counters from lid 32, all ports\n", basename);
113         fprintf(stderr, "\t\t%s -r 32 1\t# read performance counters and reset\n", basename);
114         fprintf(stderr, "\t\t%s -e -r 32 1\t# read extended performance counters and reset\n", basename);
115         fprintf(stderr, "\t\t%s -R 0x20 1\t# reset performance counters of port 1 only\n", basename);
116         fprintf(stderr, "\t\t%s -e -R 0x20 1\t# reset extended performance counters of port 1 only\n", basename);
117         fprintf(stderr, "\t\t%s -R -a 32\t# reset performance counters of all ports\n", basename);
118         fprintf(stderr, "\t\t%s -R 32 2 0x0fff\t# reset only error counters of port 2\n", basename);
119         fprintf(stderr, "\t\t%s -R 32 2 0xf000\t# reset only non-error counters of port 2\n", basename);
120         exit(-1);
121 }
122
123 /* Notes: IB semantics is to cap counters if count has exceeded limits.
124  * Therefore we must check for overflows and cap the counters if necessary.
125  *
126  * mad_decode_field and mad_encode_field assume 32 bit integers passed in
127  * for fields < 32 bits in length.
128  */
129
130 static void aggregate_4bit(uint32_t *dest, uint32_t val)
131 {
132         if ((((*dest) + val) < (*dest))
133             || ((*dest) + val) > 0xf)
134                 (*dest) = 0xf;
135         else
136                 (*dest) = (*dest) + val;
137 }
138
139 static void aggregate_8bit(uint32_t *dest, uint32_t val)
140 {
141         if ((((*dest) + val) < (*dest))
142             || ((*dest) + val) > 0xff)
143                 (*dest) = 0xff;
144         else
145                 (*dest) = (*dest) + val;
146 }
147
148 static void aggregate_16bit(uint32_t *dest, uint32_t val)
149 {
150         if ((((*dest) + val) < (*dest))
151             || ((*dest) + val) > 0xffff)
152                 (*dest) = 0xffff;
153         else
154                 (*dest) = (*dest) + val;
155 }
156
157 static void aggregate_32bit(uint32_t *dest, uint32_t val)
158 {
159         if (((*dest) + val) < (*dest))
160                 (*dest) = 0xffffffff;
161         else
162                 (*dest) = (*dest) + val;
163 }
164
165 static void aggregate_64bit(uint64_t *dest, uint64_t val)
166 {
167         if (((*dest) + val) < (*dest))
168                 (*dest) = 0xffffffffffffffffULL;
169         else
170                 (*dest) = (*dest) + val;
171 }
172
173 static void aggregate_perfcounters(void)
174 {
175         uint32_t val;
176
177         mad_decode_field(pc, IB_PC_PORT_SELECT_F, &val);
178         perf_count.portselect = val;
179         mad_decode_field(pc, IB_PC_COUNTER_SELECT_F, &val);
180         perf_count.counterselect = val;
181         mad_decode_field(pc, IB_PC_ERR_SYM_F, &val);
182         aggregate_16bit(&perf_count.symbolerrors, val);
183         mad_decode_field(pc, IB_PC_LINK_RECOVERS_F, &val);
184         aggregate_8bit(&perf_count.linkrecovers, val);
185         mad_decode_field(pc, IB_PC_LINK_DOWNED_F, &val);
186         aggregate_8bit(&perf_count.linkdowned, val);
187         mad_decode_field(pc, IB_PC_ERR_RCV_F, &val);
188         aggregate_16bit(&perf_count.rcverrors, val);
189         mad_decode_field(pc, IB_PC_ERR_PHYSRCV_F, &val);
190         aggregate_16bit(&perf_count.rcvremotephyerrors, val);
191         mad_decode_field(pc, IB_PC_ERR_SWITCH_REL_F, &val);
192         aggregate_16bit(&perf_count.rcvswrelayerrors, val);
193         mad_decode_field(pc, IB_PC_XMT_DISCARDS_F, &val);
194         aggregate_16bit(&perf_count.xmtdiscards, val);
195         mad_decode_field(pc, IB_PC_ERR_XMTCONSTR_F, &val);
196         aggregate_8bit(&perf_count.xmtconstrainterrors, val);
197         mad_decode_field(pc, IB_PC_ERR_RCVCONSTR_F, &val);
198         aggregate_8bit(&perf_count.rcvconstrainterrors, val);
199         mad_decode_field(pc, IB_PC_ERR_LOCALINTEG_F, &val);
200         aggregate_4bit(&perf_count.linkintegrityerrors, val);
201         mad_decode_field(pc, IB_PC_ERR_EXCESS_OVR_F, &val);
202         aggregate_4bit(&perf_count.excbufoverrunerrors, val);
203         mad_decode_field(pc, IB_PC_VL15_DROPPED_F, &val);
204         aggregate_16bit(&perf_count.vl15dropped, val);
205         mad_decode_field(pc, IB_PC_XMT_BYTES_F, &val);
206         aggregate_32bit(&perf_count.xmtdata, val);
207         mad_decode_field(pc, IB_PC_RCV_BYTES_F, &val);
208         aggregate_32bit(&perf_count.rcvdata, val);
209         mad_decode_field(pc, IB_PC_XMT_PKTS_F, &val);
210         aggregate_32bit(&perf_count.xmtpkts, val);
211         mad_decode_field(pc, IB_PC_RCV_PKTS_F, &val);
212         aggregate_32bit(&perf_count.rcvpkts, val);
213 }
214
215 static void output_aggregate_perfcounters(ib_portid_t *portid)
216 {
217         char buf[1024];
218         uint32_t val = ALL_PORTS;
219
220         /* set port_select to 255 to emulate AllPortSelect */
221         mad_encode_field(pc, IB_PC_PORT_SELECT_F, &val);
222         mad_encode_field(pc, IB_PC_COUNTER_SELECT_F, &perf_count.counterselect);
223         mad_encode_field(pc, IB_PC_ERR_SYM_F, &perf_count.symbolerrors);
224         mad_encode_field(pc, IB_PC_LINK_RECOVERS_F, &perf_count.linkrecovers);
225         mad_encode_field(pc, IB_PC_LINK_DOWNED_F, &perf_count.linkdowned);
226         mad_encode_field(pc, IB_PC_ERR_RCV_F, &perf_count.rcverrors);
227         mad_encode_field(pc, IB_PC_ERR_PHYSRCV_F, &perf_count.rcvremotephyerrors);
228         mad_encode_field(pc, IB_PC_ERR_SWITCH_REL_F, &perf_count.rcvswrelayerrors);
229         mad_encode_field(pc, IB_PC_XMT_DISCARDS_F, &perf_count.xmtdiscards);
230         mad_encode_field(pc, IB_PC_ERR_XMTCONSTR_F, &perf_count.xmtconstrainterrors);
231         mad_encode_field(pc, IB_PC_ERR_RCVCONSTR_F, &perf_count.rcvconstrainterrors);
232         mad_encode_field(pc, IB_PC_ERR_LOCALINTEG_F, &perf_count.linkintegrityerrors);
233         mad_encode_field(pc, IB_PC_ERR_EXCESS_OVR_F, &perf_count.excbufoverrunerrors);
234         mad_encode_field(pc, IB_PC_VL15_DROPPED_F, &perf_count.vl15dropped);
235         mad_encode_field(pc, IB_PC_XMT_BYTES_F, &perf_count.xmtdata);
236         mad_encode_field(pc, IB_PC_RCV_BYTES_F, &perf_count.rcvdata);
237         mad_encode_field(pc, IB_PC_XMT_PKTS_F, &perf_count.xmtpkts);
238         mad_encode_field(pc, IB_PC_RCV_PKTS_F, &perf_count.rcvpkts);
239
240         mad_dump_perfcounters(buf, sizeof buf, pc, sizeof pc);
241
242         printf("# Port counters: %s port %d\n%s", portid2str(portid), ALL_PORTS, buf);
243 }
244
245 static void aggregate_perfcounters_ext(void)
246 {
247         uint32_t val;
248         uint64_t val64;
249
250         mad_decode_field(pc, IB_PC_EXT_PORT_SELECT_F, &val);
251         perf_count_ext.portselect = val;
252         mad_decode_field(pc, IB_PC_EXT_COUNTER_SELECT_F, &val);
253         perf_count_ext.counterselect = val;
254         mad_decode_field(pc, IB_PC_EXT_XMT_BYTES_F, &val64);
255         aggregate_64bit(&perf_count_ext.portxmitdata, val64);
256         mad_decode_field(pc, IB_PC_EXT_RCV_BYTES_F, &val64);
257         aggregate_64bit(&perf_count_ext.portrcvdata, val64);
258         mad_decode_field(pc, IB_PC_EXT_XMT_PKTS_F, &val64);
259         aggregate_64bit(&perf_count_ext.portxmitpkts, val64);
260         mad_decode_field(pc, IB_PC_EXT_RCV_PKTS_F, &val64);
261         aggregate_64bit(&perf_count_ext.portrcvpkts, val64);
262         mad_decode_field(pc, IB_PC_EXT_XMT_UPKTS_F, &val64);
263         aggregate_64bit(&perf_count_ext.portunicastxmitpkts, val64);
264         mad_decode_field(pc, IB_PC_EXT_RCV_UPKTS_F, &val64);
265         aggregate_64bit(&perf_count_ext.portunicastrcvpkts, val64);
266         mad_decode_field(pc, IB_PC_EXT_XMT_MPKTS_F, &val64);
267         aggregate_64bit(&perf_count_ext.portmulticastxmitpkits, val64);
268         mad_decode_field(pc, IB_PC_EXT_RCV_MPKTS_F, &val64);
269         aggregate_64bit(&perf_count_ext.portmulticastrcvpkts, val64);
270 }
271
272 static void output_aggregate_perfcounters_ext(ib_portid_t *portid)
273 {
274         char buf[1024];
275         uint32_t val = ALL_PORTS;
276
277         /* set port_select to 255 to emulate AllPortSelect */
278         mad_encode_field(pc, IB_PC_EXT_PORT_SELECT_F, &val);
279         mad_encode_field(pc, IB_PC_EXT_COUNTER_SELECT_F, &perf_count_ext.counterselect);
280         mad_encode_field(pc, IB_PC_EXT_XMT_BYTES_F, &perf_count_ext.portxmitdata);
281         mad_encode_field(pc, IB_PC_EXT_RCV_BYTES_F, &perf_count_ext.portrcvdata);
282         mad_encode_field(pc, IB_PC_EXT_XMT_PKTS_F, &perf_count_ext.portxmitpkts);
283         mad_encode_field(pc, IB_PC_EXT_RCV_PKTS_F, &perf_count_ext.portrcvpkts);
284         mad_encode_field(pc, IB_PC_EXT_XMT_UPKTS_F, &perf_count_ext.portunicastxmitpkts);
285         mad_encode_field(pc, IB_PC_EXT_RCV_UPKTS_F, &perf_count_ext.portunicastrcvpkts);
286         mad_encode_field(pc, IB_PC_EXT_XMT_MPKTS_F, &perf_count_ext.portmulticastxmitpkits);
287         mad_encode_field(pc, IB_PC_EXT_RCV_MPKTS_F, &perf_count_ext.portmulticastrcvpkts);
288
289         mad_dump_perfcounters_ext(buf, sizeof buf, pc, sizeof pc);
290
291         printf("# Port counters: %s port %d\n%s", portid2str(portid), ALL_PORTS, buf);
292 }
293
294 static void dump_perfcounters(int extended, int timeout, uint16_t cap_mask, ib_portid_t *portid,
295                               int port, int aggregate)
296 {
297         char buf[1024];
298
299         if (extended != 1) {
300                 if (!port_performance_query(pc, portid, port, timeout))
301                         IBERROR("perfquery");
302                 if (aggregate)
303                         aggregate_perfcounters();
304                 else
305                         mad_dump_perfcounters(buf, sizeof buf, pc, sizeof pc);
306         } else {
307                 if (!(cap_mask & 0x200)) /* 1.2 errata: bit 9 is extended counter support */
308                         IBWARN("PerfMgt ClassPortInfo 0x%x extended counters not indicated\n", cap_mask);
309
310                 if (!port_performance_ext_query(pc, portid, port, timeout))
311                         IBERROR("perfextquery");
312                 if (aggregate)
313                         aggregate_perfcounters_ext();
314                 else
315                         mad_dump_perfcounters_ext(buf, sizeof buf, pc, sizeof pc);
316         }
317
318         if (!aggregate)
319                 printf("# Port counters: %s port %d\n%s", portid2str(portid), port, buf);
320 }
321
322 static void reset_counters(int extended, int timeout, int mask, ib_portid_t *portid, int port)
323 {
324         if (extended != 1) {
325                 if (!port_performance_reset(pc, portid, port, mask, timeout))
326                         IBERROR("perf reset");
327         } else {
328                 if (!port_performance_ext_reset(pc, portid, port, mask, timeout))
329                         IBERROR("perf ext reset");
330         }
331 }
332
333 int
334 main(int argc, char **argv)
335 {
336         int mgmt_classes[4] = {IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS, IB_PERFORMANCE_CLASS};
337         ib_portid_t *sm_id = 0, sm_portid = {0};
338         ib_portid_t portid = {0};
339         extern int ibdebug;
340         int dest_type = IB_DEST_LID;
341         int timeout = 0;        /* use default */
342         int mask = 0xffff, all_ports = 0;
343         int reset = 0, reset_only = 0;
344         int port = 0;
345         int udebug = 0;
346         char *ca = 0;
347         int ca_port = 0;
348         int extended = 0;
349         uint16_t cap_mask;
350         int all_ports_loop = 0;
351         int loop_ports = 0;
352         int node_type, num_ports = 0;
353         uint8_t data[IB_SMP_DATA_SIZE];
354         int start_port = 1;
355         int enhancedport0;
356         int i;
357
358         static char const str_opts[] = "C:P:s:t:dGealrRVhu";
359         static const struct option long_opts[] = {
360                 { "C", 1, 0, 'C'},
361                 { "P", 1, 0, 'P'},
362                 { "debug", 0, 0, 'd'},
363                 { "Guid", 0, 0, 'G'},
364                 { "extended", 0, 0, 'e'},
365                 { "all_ports", 0, 0, 'a'},
366                 { "loop_ports", 0, 0, 'l'},
367                 { "reset_after_read", 0, 0, 'r'},
368                 { "Reset_only", 0, 0, 'R'},
369                 { "sm_portid", 1, 0, 's'},
370                 { "timeout", 1, 0, 't'},
371                 { "Version", 0, 0, 'V'},
372                 { "help", 0, 0, 'h'},
373                 { "usage", 0, 0, 'u'},
374                 { }
375         };
376
377         argv0 = argv[0];
378
379         while (1) {
380                 int ch = getopt_long(argc, argv, str_opts, long_opts, NULL);
381                 if ( ch == -1 )
382                         break;
383                 switch(ch) {
384                 case 'C':
385                         ca = optarg;
386                         break;
387                 case 'P':
388                         ca_port = strtoul(optarg, 0, 0);
389                         break;
390                 case 'e':
391                         extended = 1;
392                         break;
393                 case 'a':
394                         all_ports++;
395                         port = ALL_PORTS;
396                         break;
397                 case 'l':
398                         loop_ports++;
399                         break;
400                 case 'd':
401                         ibdebug++;
402                         madrpc_show_errors(1);
403                         umad_debug(udebug);
404                         udebug++;
405                         break;
406                 case 'G':
407                         dest_type = IB_DEST_GUID;
408                         break;
409                 case 's':
410                         if (ib_resolve_portid_str(&sm_portid, optarg, IB_DEST_LID, 0) < 0)
411                                 IBERROR("can't resolve SM destination port %s", optarg);
412                         sm_id = &sm_portid;
413                         break;
414                 case 'r':
415                         reset++;
416                         break;
417                 case 'R':
418                         reset_only++;
419                         break;
420                 case 't':
421                         timeout = strtoul(optarg, 0, 0);
422                         madrpc_set_timeout(timeout);
423                         break;
424                 case 'V':
425                         fprintf(stderr, "%s %s\n", argv0, get_build_version() );
426                         exit(-1);
427                 default:
428                         usage();
429                         break;
430                 }
431         }
432         argc -= optind;
433         argv += optind;
434
435         if (argc > 1)
436                 port = strtoul(argv[1], 0, 0);
437         if (argc > 2)
438                 mask = strtoul(argv[2], 0, 0);
439
440         madrpc_init(ca, ca_port, mgmt_classes, 4);
441
442         if (argc) {
443                 if (ib_resolve_portid_str(&portid, argv[0], dest_type, sm_id) < 0)
444                         IBERROR("can't resolve destination port %s", argv[0]);
445         } else {
446                 if (ib_resolve_self(&portid, &port, 0) < 0)
447                         IBERROR("can't resolve self port %s", argv[0]);
448         }
449
450         /* PerfMgt ClassPortInfo is a required attribute */
451         if (!perf_classportinfo_query(pc, &portid, port, timeout))
452                 IBERROR("classportinfo query");
453         /* ClassPortInfo should be supported as part of libibmad */
454         memcpy(&cap_mask, pc+2, sizeof(cap_mask));      /* CapabilityMask */
455         cap_mask = ntohs(cap_mask);
456         if (!(cap_mask & 0x100)) { /* bit 8 is AllPortSelect */
457                 if (!all_ports && port == ALL_PORTS)
458                         IBERROR("AllPortSelect not supported");
459                 if (all_ports)
460                         all_ports_loop = 1;
461         }
462
463         if (all_ports_loop || (loop_ports && (all_ports || port == ALL_PORTS))) {
464                 if (smp_query(data, &portid, IB_ATTR_NODE_INFO, 0, 0) < 0)
465                         IBERROR("smp query nodeinfo failed");
466                 node_type = mad_get_field(data, 0, IB_NODE_TYPE_F);
467                 mad_decode_field(data, IB_NODE_NPORTS_F, &num_ports);
468                 if (!num_ports)
469                         IBERROR("smp query nodeinfo: num ports invalid");
470
471                 if (node_type == IB_NODE_SWITCH) {
472                         if (smp_query(data, &portid, IB_ATTR_SWITCH_INFO, 0, 0) < 0)
473                                 IBERROR("smp query nodeinfo failed");
474                         enhancedport0 = mad_get_field(data, 0, IB_SW_ENHANCED_PORT0_F);
475                         if (enhancedport0)
476                                 start_port = 0;
477                 }
478                 if (all_ports_loop && !loop_ports)
479                         IBWARN("Emulating AllPortSelect by iterating through all ports");
480         }
481
482         if (reset_only)
483                 goto do_reset;
484
485         if (all_ports_loop || (loop_ports && (all_ports || port == ALL_PORTS))) {
486                 for (i = start_port; i <= num_ports; i++)
487                         dump_perfcounters(extended, timeout, cap_mask, &portid, i,
488                                           (all_ports_loop && !loop_ports));
489                 if (all_ports_loop && !loop_ports) {
490                         if (extended != 1)
491                                 output_aggregate_perfcounters(&portid);
492                         else
493                                 output_aggregate_perfcounters_ext(&portid);
494                 }
495         }
496         else
497                 dump_perfcounters(extended, timeout, cap_mask, &portid, port, 0);
498
499         if (!reset)
500                 exit(0);
501
502 do_reset:
503
504         if (all_ports_loop || (loop_ports && (all_ports || port == ALL_PORTS))) {
505                 for (i = start_port; i <= num_ports; i++)
506                         reset_counters(extended, timeout, mask, &portid, i);
507         }
508         else
509                 reset_counters(extended, timeout, mask, &portid, port);
510
511         exit(0);
512 }