2 * Copyright (c) 2004-2008 Voltaire Inc. All rights reserved.
3 * Copyright (c) 2007 Xsigo Systems Inc. All rights reserved.
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:
11 * Redistribution and use in source and binary forms, with or
12 * without modification, are permitted provided that the following
15 * - Redistributions of source code must retain the above
16 * copyright notice, this list of conditions and the following
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.
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
37 #endif /* HAVE_CONFIG_H */
44 #include <netinet/in.h>
46 #include <infiniband/common.h>
47 #include <infiniband/umad.h>
48 #include <infiniband/mad.h>
50 #include "ibdiag_common.h"
54 uint32_t counterselect;
55 uint32_t symbolerrors;
56 uint32_t linkrecovers;
59 uint32_t rcvremotephyerrors;
60 uint32_t rcvswrelayerrors;
62 uint32_t xmtconstrainterrors;
63 uint32_t rcvconstrainterrors;
64 uint32_t linkintegrityerrors;
65 uint32_t excbufoverrunerrors;
73 struct perf_count_ext {
75 uint32_t counterselect;
76 uint64_t portxmitdata;
78 uint64_t portxmitpkts;
80 uint64_t portunicastxmitpkts;
81 uint64_t portunicastrcvpkts;
82 uint64_t portmulticastxmitpkits;
83 uint64_t portmulticastrcvpkts;
86 static uint8_t pc[1024];
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};
91 char *argv0 = "perfquery";
93 #define ALL_PORTS 0xFF
100 if (!(basename = strrchr(argv0, '/')))
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",
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);
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.
126 * mad_decode_field and mad_encode_field assume 32 bit integers passed in
127 * for fields < 32 bits in length.
130 static void aggregate_4bit(uint32_t *dest, uint32_t val)
132 if ((((*dest) + val) < (*dest))
133 || ((*dest) + val) > 0xf)
136 (*dest) = (*dest) + val;
139 static void aggregate_8bit(uint32_t *dest, uint32_t val)
141 if ((((*dest) + val) < (*dest))
142 || ((*dest) + val) > 0xff)
145 (*dest) = (*dest) + val;
148 static void aggregate_16bit(uint32_t *dest, uint32_t val)
150 if ((((*dest) + val) < (*dest))
151 || ((*dest) + val) > 0xffff)
154 (*dest) = (*dest) + val;
157 static void aggregate_32bit(uint32_t *dest, uint32_t val)
159 if (((*dest) + val) < (*dest))
160 (*dest) = 0xffffffff;
162 (*dest) = (*dest) + val;
165 static void aggregate_64bit(uint64_t *dest, uint64_t val)
167 if (((*dest) + val) < (*dest))
168 (*dest) = 0xffffffffffffffffULL;
170 (*dest) = (*dest) + val;
173 static void aggregate_perfcounters(void)
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);
215 static void output_aggregate_perfcounters(ib_portid_t *portid)
218 uint32_t val = ALL_PORTS;
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);
240 mad_dump_perfcounters(buf, sizeof buf, pc, sizeof pc);
242 printf("# Port counters: %s port %d\n%s", portid2str(portid), ALL_PORTS, buf);
245 static void aggregate_perfcounters_ext(void)
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);
272 static void output_aggregate_perfcounters_ext(ib_portid_t *portid)
275 uint32_t val = ALL_PORTS;
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);
289 mad_dump_perfcounters_ext(buf, sizeof buf, pc, sizeof pc);
291 printf("# Port counters: %s port %d\n%s", portid2str(portid), ALL_PORTS, buf);
294 static void dump_perfcounters(int extended, int timeout, uint16_t cap_mask, ib_portid_t *portid,
295 int port, int aggregate)
300 if (!port_performance_query(pc, portid, port, timeout))
301 IBERROR("perfquery");
303 aggregate_perfcounters();
305 mad_dump_perfcounters(buf, sizeof buf, pc, sizeof pc);
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);
310 if (!port_performance_ext_query(pc, portid, port, timeout))
311 IBERROR("perfextquery");
313 aggregate_perfcounters_ext();
315 mad_dump_perfcounters_ext(buf, sizeof buf, pc, sizeof pc);
319 printf("# Port counters: %s port %d\n%s", portid2str(portid), port, buf);
322 static void reset_counters(int extended, int timeout, int mask, ib_portid_t *portid, int port)
325 if (!port_performance_reset(pc, portid, port, mask, timeout))
326 IBERROR("perf reset");
328 if (!port_performance_ext_reset(pc, portid, port, mask, timeout))
329 IBERROR("perf ext reset");
334 main(int argc, char **argv)
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};
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;
350 int all_ports_loop = 0;
352 int node_type, num_ports = 0;
353 uint8_t data[IB_SMP_DATA_SIZE];
358 static char const str_opts[] = "C:P:s:t:dGealrRVhu";
359 static const struct option long_opts[] = {
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'},
380 int ch = getopt_long(argc, argv, str_opts, long_opts, NULL);
388 ca_port = strtoul(optarg, 0, 0);
402 madrpc_show_errors(1);
407 dest_type = IB_DEST_GUID;
410 if (ib_resolve_portid_str(&sm_portid, optarg, IB_DEST_LID, 0) < 0)
411 IBERROR("can't resolve SM destination port %s", optarg);
421 timeout = strtoul(optarg, 0, 0);
422 madrpc_set_timeout(timeout);
425 fprintf(stderr, "%s %s\n", argv0, get_build_version() );
436 port = strtoul(argv[1], 0, 0);
438 mask = strtoul(argv[2], 0, 0);
440 madrpc_init(ca, ca_port, mgmt_classes, 4);
443 if (ib_resolve_portid_str(&portid, argv[0], dest_type, sm_id) < 0)
444 IBERROR("can't resolve destination port %s", argv[0]);
446 if (ib_resolve_self(&portid, &port, 0) < 0)
447 IBERROR("can't resolve self port %s", argv[0]);
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");
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);
469 IBERROR("smp query nodeinfo: num ports invalid");
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);
478 if (all_ports_loop && !loop_ports)
479 IBWARN("Emulating AllPortSelect by iterating through all ports");
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) {
491 output_aggregate_perfcounters(&portid);
493 output_aggregate_perfcounters_ext(&portid);
497 dump_perfcounters(extended, timeout, cap_mask, &portid, port, 0);
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);
509 reset_counters(extended, timeout, mask, &portid, port);