2 * Copyright (c) 2004-2009 Voltaire Inc. All rights reserved.
3 * Copyright (c) 2007 Xsigo Systems Inc. All rights reserved.
4 * Copyright (c) 2009 HNR Consulting. All rights reserved.
5 * Copyright (c) 2011 Mellanox Technologies LTD. All rights reserved.
7 * This software is available to you under a choice of one of two
8 * licenses. You may choose to be licensed under the terms of the GNU
9 * General Public License (GPL) Version 2, available from the file
10 * COPYING in the main directory of this source tree, or the
11 * OpenIB.org BSD license below:
13 * Redistribution and use in source and binary forms, with or
14 * without modification, are permitted provided that the following
17 * - Redistributions of source code must retain the above
18 * copyright notice, this list of conditions and the following
21 * - Redistributions in binary form must reproduce the above
22 * copyright notice, this list of conditions and the following
23 * disclaimer in the documentation and/or other materials
24 * provided with the distribution.
26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
30 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
31 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
32 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39 #endif /* HAVE_CONFIG_H */
45 #include <netinet/in.h>
47 #include <infiniband/umad.h>
48 #include <infiniband/mad.h>
49 #include <infiniband/iba/ib_types.h>
51 #include "ibdiag_common.h"
53 struct ibmad_port *srcport;
55 static ibmad_gid_t dgid;
60 uint32_t counterselect;
61 uint32_t symbolerrors;
62 uint32_t linkrecovers;
65 uint32_t rcvremotephyerrors;
66 uint32_t rcvswrelayerrors;
68 uint32_t xmtconstrainterrors;
69 uint32_t rcvconstrainterrors;
70 uint32_t linkintegrityerrors;
71 uint32_t excbufoverrunerrors;
81 struct perf_count_ext {
83 uint32_t counterselect;
84 uint64_t portxmitdata;
86 uint64_t portxmitpkts;
88 uint64_t portunicastxmitpkts;
89 uint64_t portunicastrcvpkts;
90 uint64_t portmulticastxmitpkits;
91 uint64_t portmulticastrcvpkts;
93 uint32_t counterSelect2;
94 uint64_t symbolErrorCounter;
95 uint64_t linkErrorRecoveryCounter;
96 uint64_t linkDownedCounter;
97 uint64_t portRcvErrors;
98 uint64_t portRcvRemotePhysicalErrors;
99 uint64_t portRcvSwitchRelayErrors;
100 uint64_t portXmitDiscards;
101 uint64_t portXmitConstraintErrors;
102 uint64_t portRcvConstraintErrors;
103 uint64_t localLinkIntegrityErrors;
104 uint64_t excessiveBufferOverrunErrors;
105 uint64_t VL15Dropped;
106 uint64_t portXmitWait;
110 static uint8_t pc[1024];
112 struct perf_count perf_count = {0};
113 struct perf_count_ext perf_count_ext = {0};
115 #define ALL_PORTS 0xFF
116 #define MAX_PORTS 255
118 /* Notes: IB semantics is to cap counters if count has exceeded limits.
119 * Therefore we must check for overflows and cap the counters if necessary.
121 * mad_decode_field and mad_encode_field assume 32 bit integers passed in
122 * for fields < 32 bits in length.
125 static void aggregate_4bit(uint32_t * dest, uint32_t val)
127 if ((((*dest) + val) < (*dest)) || ((*dest) + val) > 0xf)
130 (*dest) = (*dest) + val;
133 static void aggregate_8bit(uint32_t * dest, uint32_t val)
135 if ((((*dest) + val) < (*dest))
136 || ((*dest) + val) > 0xff)
139 (*dest) = (*dest) + val;
142 static void aggregate_16bit(uint32_t * dest, uint32_t val)
144 if ((((*dest) + val) < (*dest))
145 || ((*dest) + val) > 0xffff)
148 (*dest) = (*dest) + val;
151 static void aggregate_32bit(uint32_t * dest, uint32_t val)
153 if (((*dest) + val) < (*dest))
154 (*dest) = 0xffffffff;
156 (*dest) = (*dest) + val;
159 static void aggregate_64bit(uint64_t * dest, uint64_t val)
161 if (((*dest) + val) < (*dest))
162 (*dest) = 0xffffffffffffffffULL;
164 (*dest) = (*dest) + val;
167 static void aggregate_perfcounters(void)
171 mad_decode_field(pc, IB_PC_PORT_SELECT_F, &val);
172 perf_count.portselect = val;
173 mad_decode_field(pc, IB_PC_COUNTER_SELECT_F, &val);
174 perf_count.counterselect = val;
175 mad_decode_field(pc, IB_PC_ERR_SYM_F, &val);
176 aggregate_16bit(&perf_count.symbolerrors, val);
177 mad_decode_field(pc, IB_PC_LINK_RECOVERS_F, &val);
178 aggregate_8bit(&perf_count.linkrecovers, val);
179 mad_decode_field(pc, IB_PC_LINK_DOWNED_F, &val);
180 aggregate_8bit(&perf_count.linkdowned, val);
181 mad_decode_field(pc, IB_PC_ERR_RCV_F, &val);
182 aggregate_16bit(&perf_count.rcverrors, val);
183 mad_decode_field(pc, IB_PC_ERR_PHYSRCV_F, &val);
184 aggregate_16bit(&perf_count.rcvremotephyerrors, val);
185 mad_decode_field(pc, IB_PC_ERR_SWITCH_REL_F, &val);
186 aggregate_16bit(&perf_count.rcvswrelayerrors, val);
187 mad_decode_field(pc, IB_PC_XMT_DISCARDS_F, &val);
188 aggregate_16bit(&perf_count.xmtdiscards, val);
189 mad_decode_field(pc, IB_PC_ERR_XMTCONSTR_F, &val);
190 aggregate_8bit(&perf_count.xmtconstrainterrors, val);
191 mad_decode_field(pc, IB_PC_ERR_RCVCONSTR_F, &val);
192 aggregate_8bit(&perf_count.rcvconstrainterrors, val);
193 mad_decode_field(pc, IB_PC_ERR_LOCALINTEG_F, &val);
194 aggregate_4bit(&perf_count.linkintegrityerrors, val);
195 mad_decode_field(pc, IB_PC_ERR_EXCESS_OVR_F, &val);
196 aggregate_4bit(&perf_count.excbufoverrunerrors, val);
197 #ifdef HAVE_IB_PC_QP1_DROP_F
198 mad_decode_field(pc, IB_PC_QP1_DROP_F, &val);
199 aggregate_16bit(&perf_count.qp1dropped, val);
201 mad_decode_field(pc, IB_PC_VL15_DROPPED_F, &val);
202 aggregate_16bit(&perf_count.vl15dropped, val);
203 mad_decode_field(pc, IB_PC_XMT_BYTES_F, &val);
204 aggregate_32bit(&perf_count.xmtdata, val);
205 mad_decode_field(pc, IB_PC_RCV_BYTES_F, &val);
206 aggregate_32bit(&perf_count.rcvdata, val);
207 mad_decode_field(pc, IB_PC_XMT_PKTS_F, &val);
208 aggregate_32bit(&perf_count.xmtpkts, val);
209 mad_decode_field(pc, IB_PC_RCV_PKTS_F, &val);
210 aggregate_32bit(&perf_count.rcvpkts, val);
211 mad_decode_field(pc, IB_PC_XMT_WAIT_F, &val);
212 aggregate_32bit(&perf_count.xmtwait, val);
215 static void output_aggregate_perfcounters(ib_portid_t * portid,
219 uint32_t val = ALL_PORTS;
221 /* set port_select to 255 to emulate AllPortSelect */
222 mad_encode_field(pc, IB_PC_PORT_SELECT_F, &val);
223 mad_encode_field(pc, IB_PC_COUNTER_SELECT_F, &perf_count.counterselect);
224 mad_encode_field(pc, IB_PC_ERR_SYM_F, &perf_count.symbolerrors);
225 mad_encode_field(pc, IB_PC_LINK_RECOVERS_F, &perf_count.linkrecovers);
226 mad_encode_field(pc, IB_PC_LINK_DOWNED_F, &perf_count.linkdowned);
227 mad_encode_field(pc, IB_PC_ERR_RCV_F, &perf_count.rcverrors);
228 mad_encode_field(pc, IB_PC_ERR_PHYSRCV_F,
229 &perf_count.rcvremotephyerrors);
230 mad_encode_field(pc, IB_PC_ERR_SWITCH_REL_F,
231 &perf_count.rcvswrelayerrors);
232 mad_encode_field(pc, IB_PC_XMT_DISCARDS_F, &perf_count.xmtdiscards);
233 mad_encode_field(pc, IB_PC_ERR_XMTCONSTR_F,
234 &perf_count.xmtconstrainterrors);
235 mad_encode_field(pc, IB_PC_ERR_RCVCONSTR_F,
236 &perf_count.rcvconstrainterrors);
237 mad_encode_field(pc, IB_PC_ERR_LOCALINTEG_F,
238 &perf_count.linkintegrityerrors);
239 mad_encode_field(pc, IB_PC_ERR_EXCESS_OVR_F,
240 &perf_count.excbufoverrunerrors);
241 #ifdef HAVE_IB_PC_QP1_DROP_F
242 mad_encode_field(pc, IB_PC_QP1_DROP_F, &perf_count.qp1dropped);
244 mad_encode_field(pc, IB_PC_VL15_DROPPED_F, &perf_count.vl15dropped);
245 mad_encode_field(pc, IB_PC_XMT_BYTES_F, &perf_count.xmtdata);
246 mad_encode_field(pc, IB_PC_RCV_BYTES_F, &perf_count.rcvdata);
247 mad_encode_field(pc, IB_PC_XMT_PKTS_F, &perf_count.xmtpkts);
248 mad_encode_field(pc, IB_PC_RCV_PKTS_F, &perf_count.rcvpkts);
249 mad_encode_field(pc, IB_PC_XMT_WAIT_F, &perf_count.xmtwait);
251 mad_dump_perfcounters(buf, sizeof buf, pc, sizeof pc);
253 printf("# Port counters: %s port %d (CapMask: 0x%02X)\n%s",
254 portid2str(portid), ALL_PORTS, ntohs(cap_mask), buf);
257 static void aggregate_perfcounters_ext(uint16_t cap_mask, uint32_t cap_mask2)
262 mad_decode_field(pc, IB_PC_EXT_PORT_SELECT_F, &val);
263 perf_count_ext.portselect = val;
264 mad_decode_field(pc, IB_PC_EXT_COUNTER_SELECT_F, &val);
265 perf_count_ext.counterselect = val;
266 mad_decode_field(pc, IB_PC_EXT_XMT_BYTES_F, &val64);
267 aggregate_64bit(&perf_count_ext.portxmitdata, val64);
268 mad_decode_field(pc, IB_PC_EXT_RCV_BYTES_F, &val64);
269 aggregate_64bit(&perf_count_ext.portrcvdata, val64);
270 mad_decode_field(pc, IB_PC_EXT_XMT_PKTS_F, &val64);
271 aggregate_64bit(&perf_count_ext.portxmitpkts, val64);
272 mad_decode_field(pc, IB_PC_EXT_RCV_PKTS_F, &val64);
273 aggregate_64bit(&perf_count_ext.portrcvpkts, val64);
275 if (cap_mask & IB_PM_EXT_WIDTH_SUPPORTED) {
276 mad_decode_field(pc, IB_PC_EXT_XMT_UPKTS_F, &val64);
277 aggregate_64bit(&perf_count_ext.portunicastxmitpkts, val64);
278 mad_decode_field(pc, IB_PC_EXT_RCV_UPKTS_F, &val64);
279 aggregate_64bit(&perf_count_ext.portunicastrcvpkts, val64);
280 mad_decode_field(pc, IB_PC_EXT_XMT_MPKTS_F, &val64);
281 aggregate_64bit(&perf_count_ext.portmulticastxmitpkits, val64);
282 mad_decode_field(pc, IB_PC_EXT_RCV_MPKTS_F, &val64);
283 aggregate_64bit(&perf_count_ext.portmulticastrcvpkts, val64);
286 if (htonl(cap_mask2) & IB_PM_IS_ADDL_PORT_CTRS_EXT_SUP) {
287 mad_decode_field(pc, IB_PC_EXT_COUNTER_SELECT2_F, &val);
288 perf_count_ext.counterSelect2 = val;
289 mad_decode_field(pc, IB_PC_EXT_ERR_SYM_F, &val64);
290 aggregate_64bit(&perf_count_ext.symbolErrorCounter, val64);
291 mad_decode_field(pc, IB_PC_EXT_LINK_RECOVERS_F, &val64);
292 aggregate_64bit(&perf_count_ext.linkErrorRecoveryCounter, val64);
293 mad_decode_field(pc, IB_PC_EXT_LINK_DOWNED_F, &val64);
294 aggregate_64bit(&perf_count_ext.linkDownedCounter, val64);
295 mad_decode_field(pc, IB_PC_EXT_ERR_RCV_F, &val64);
296 aggregate_64bit(&perf_count_ext.portRcvErrors, val64);
297 mad_decode_field(pc, IB_PC_EXT_ERR_PHYSRCV_F, &val64);
298 aggregate_64bit(&perf_count_ext.portRcvRemotePhysicalErrors, val64);
299 mad_decode_field(pc, IB_PC_EXT_ERR_SWITCH_REL_F, &val64);
300 aggregate_64bit(&perf_count_ext.portRcvSwitchRelayErrors, val64);
301 mad_decode_field(pc, IB_PC_EXT_XMT_DISCARDS_F, &val64);
302 aggregate_64bit(&perf_count_ext.portXmitDiscards, val64);
303 mad_decode_field(pc, IB_PC_EXT_ERR_XMTCONSTR_F, &val64);
304 aggregate_64bit(&perf_count_ext.portXmitConstraintErrors, val64);
305 mad_decode_field(pc, IB_PC_EXT_ERR_RCVCONSTR_F, &val64);
306 aggregate_64bit(&perf_count_ext.portRcvConstraintErrors, val64);
307 mad_decode_field(pc, IB_PC_EXT_ERR_LOCALINTEG_F, &val64);
308 aggregate_64bit(&perf_count_ext.localLinkIntegrityErrors, val64);
309 mad_decode_field(pc, IB_PC_EXT_ERR_EXCESS_OVR_F, &val64);
310 aggregate_64bit(&perf_count_ext.excessiveBufferOverrunErrors, val64);
311 mad_decode_field(pc, IB_PC_EXT_VL15_DROPPED_F, &val64);
312 aggregate_64bit(&perf_count_ext.VL15Dropped, val64);
313 mad_decode_field(pc, IB_PC_EXT_XMT_WAIT_F, &val64);
314 aggregate_64bit(&perf_count_ext.portXmitWait, val64);
315 mad_decode_field(pc, IB_PC_EXT_QP1_DROP_F, &val64);
316 aggregate_64bit(&perf_count_ext.QP1Dropped, val64);
320 static void output_aggregate_perfcounters_ext(ib_portid_t * portid,
321 uint16_t cap_mask, uint32_t cap_mask2)
324 uint32_t val = ALL_PORTS;
326 memset(buf, 0, sizeof(buf));
328 /* set port_select to 255 to emulate AllPortSelect */
329 mad_encode_field(pc, IB_PC_EXT_PORT_SELECT_F, &val);
330 mad_encode_field(pc, IB_PC_EXT_COUNTER_SELECT_F,
331 &perf_count_ext.counterselect);
332 mad_encode_field(pc, IB_PC_EXT_XMT_BYTES_F,
333 &perf_count_ext.portxmitdata);
334 mad_encode_field(pc, IB_PC_EXT_RCV_BYTES_F,
335 &perf_count_ext.portrcvdata);
336 mad_encode_field(pc, IB_PC_EXT_XMT_PKTS_F,
337 &perf_count_ext.portxmitpkts);
338 mad_encode_field(pc, IB_PC_EXT_RCV_PKTS_F, &perf_count_ext.portrcvpkts);
340 if (cap_mask & IB_PM_EXT_WIDTH_SUPPORTED) {
341 mad_encode_field(pc, IB_PC_EXT_XMT_UPKTS_F,
342 &perf_count_ext.portunicastxmitpkts);
343 mad_encode_field(pc, IB_PC_EXT_RCV_UPKTS_F,
344 &perf_count_ext.portunicastrcvpkts);
345 mad_encode_field(pc, IB_PC_EXT_XMT_MPKTS_F,
346 &perf_count_ext.portmulticastxmitpkits);
347 mad_encode_field(pc, IB_PC_EXT_RCV_MPKTS_F,
348 &perf_count_ext.portmulticastrcvpkts);
351 if (htonl(cap_mask2) & IB_PM_IS_ADDL_PORT_CTRS_EXT_SUP) {
352 mad_encode_field(pc, IB_PC_EXT_COUNTER_SELECT2_F,
353 &perf_count_ext.counterSelect2);
354 mad_encode_field(pc, IB_PC_EXT_ERR_SYM_F,
355 &perf_count_ext.symbolErrorCounter);
356 mad_encode_field(pc, IB_PC_EXT_LINK_RECOVERS_F,
357 &perf_count_ext.linkErrorRecoveryCounter);
358 mad_encode_field(pc, IB_PC_EXT_LINK_DOWNED_F,
359 &perf_count_ext.linkDownedCounter);
360 mad_encode_field(pc, IB_PC_EXT_ERR_RCV_F,
361 &perf_count_ext.portRcvErrors);
362 mad_encode_field(pc, IB_PC_EXT_ERR_PHYSRCV_F,
363 &perf_count_ext.portRcvRemotePhysicalErrors);
364 mad_encode_field(pc, IB_PC_EXT_ERR_SWITCH_REL_F,
365 &perf_count_ext.portRcvSwitchRelayErrors);
366 mad_encode_field(pc, IB_PC_EXT_XMT_DISCARDS_F,
367 &perf_count_ext.portXmitDiscards);
368 mad_encode_field(pc, IB_PC_EXT_ERR_XMTCONSTR_F,
369 &perf_count_ext.portXmitConstraintErrors);
370 mad_encode_field(pc, IB_PC_EXT_ERR_RCVCONSTR_F,
371 &perf_count_ext.portRcvConstraintErrors);
372 mad_encode_field(pc, IB_PC_EXT_ERR_LOCALINTEG_F,
373 &perf_count_ext.localLinkIntegrityErrors);
374 mad_encode_field(pc, IB_PC_EXT_ERR_EXCESS_OVR_F,
375 &perf_count_ext.excessiveBufferOverrunErrors);
376 mad_encode_field(pc, IB_PC_EXT_VL15_DROPPED_F,
377 &perf_count_ext.VL15Dropped);
378 mad_encode_field(pc, IB_PC_EXT_XMT_WAIT_F,
379 &perf_count_ext.portXmitWait);
380 mad_encode_field(pc, IB_PC_EXT_QP1_DROP_F,
381 &perf_count_ext.QP1Dropped);
384 mad_dump_perfcounters_ext(buf, sizeof buf, pc, sizeof pc);
386 printf("# Port extended counters: %s port %d (CapMask: 0x%02X CapMask2: 0x%07X)\n%s",
387 portid2str(portid), ALL_PORTS, ntohs(cap_mask), cap_mask2, buf);
390 static void dump_perfcounters(int extended, int timeout, uint16_t cap_mask,
391 uint32_t cap_mask2, ib_portid_t * portid,
392 int port, int aggregate)
397 memset(pc, 0, sizeof(pc));
398 if (!pma_query_via(pc, portid, port, timeout,
399 IB_GSI_PORT_COUNTERS, srcport))
401 if (!(cap_mask & IB_PM_PC_XMIT_WAIT_SUP)) {
402 /* if PortCounters:PortXmitWait not supported clear this counter */
403 VERBOSE("PortXmitWait not indicated"
404 " so ignore this counter");
405 perf_count.xmtwait = 0;
406 mad_encode_field(pc, IB_PC_XMT_WAIT_F,
407 &perf_count.xmtwait);
410 aggregate_perfcounters();
412 #ifdef HAVE_IB_PC_QP1_DROP_F
413 mad_dump_perfcounters(buf, sizeof buf, pc, sizeof pc);
415 mad_dump_fields(buf, sizeof buf, pc, sizeof pc,
417 (cap_mask & IB_PM_PC_XMIT_WAIT_SUP)?IB_PC_LAST_F:(IB_PC_RCV_PKTS_F+1));
421 /* 1.2 errata: bit 9 is extended counter support
422 * bit 10 is extended counter NoIETF
424 if (!(cap_mask & IB_PM_EXT_WIDTH_SUPPORTED) &&
425 !(cap_mask & IB_PM_EXT_WIDTH_NOIETF_SUP))
427 ("PerfMgt ClassPortInfo CapMask 0x%02X; No extended counter support indicated\n",
430 memset(pc, 0, sizeof(pc));
431 if (!pma_query_via(pc, portid, port, timeout,
432 IB_GSI_PORT_COUNTERS_EXT, srcport))
433 IBEXIT("perfextquery");
435 aggregate_perfcounters_ext(cap_mask, cap_mask2);
437 mad_dump_perfcounters_ext(buf, sizeof buf, pc,
443 printf("# Port extended counters: %s port %d "
444 "(CapMask: 0x%02X CapMask2: 0x%07X)\n%s",
445 portid2str(portid), port, ntohs(cap_mask),
448 printf("# Port counters: %s port %d "
449 "(CapMask: 0x%02X)\n%s",
450 portid2str(portid), port, ntohs(cap_mask), buf);
454 static void reset_counters(int extended, int timeout, int mask,
455 ib_portid_t * portid, int port)
457 memset(pc, 0, sizeof(pc));
459 if (!performance_reset_via(pc, portid, port, mask, timeout,
460 IB_GSI_PORT_COUNTERS, srcport))
461 IBEXIT("perf reset");
463 if (!performance_reset_via(pc, portid, port, mask, timeout,
464 IB_GSI_PORT_COUNTERS_EXT, srcport))
465 IBEXIT("perf ext reset");
469 static int reset, reset_only, all_ports, loop_ports, port, extended, xmt_sl,
470 rcv_sl, xmt_disc, rcv_err, extended_speeds, smpl_ctl, oprcvcounters, flowctlcounters,
471 vloppackets, vlopdata, vlxmitflowctlerrors, vlxmitcounters, swportvlcong,
472 rcvcc, slrcvfecn, slrcvbecn, xmitcc, vlxmittimecc;
473 static int ports[MAX_PORTS];
474 static int ports_count;
476 static void common_func(ib_portid_t * portid, int port_num, int mask,
477 unsigned query, unsigned reset,
478 const char *name, uint16_t attr,
479 void dump_func(char *, int, void *, int))
484 memset(pc, 0, sizeof(pc));
485 if (!pma_query_via(pc, portid, port_num, ibd_timeout, attr,
487 IBEXIT("cannot query %s", name);
489 dump_func(buf, sizeof(buf), pc, sizeof(pc));
491 printf("# %s counters: %s port %d\n%s", name,
492 portid2str(portid), port_num, buf);
495 memset(pc, 0, sizeof(pc));
496 if (reset && !performance_reset_via(pc, portid, port, mask, ibd_timeout,
498 IBEXIT("cannot reset %s", name);
501 static void xmt_sl_query(ib_portid_t * portid, int port, int mask)
503 common_func(portid, port, mask, !reset_only, (reset_only || reset),
504 "PortXmitDataSL", IB_GSI_PORT_XMIT_DATA_SL,
505 mad_dump_perfcounters_xmt_sl);
508 static void rcv_sl_query(ib_portid_t * portid, int port, int mask)
510 common_func(portid, port, mask, !reset_only, (reset_only || reset),
511 "PortRcvDataSL", IB_GSI_PORT_RCV_DATA_SL,
512 mad_dump_perfcounters_rcv_sl);
515 static void xmt_disc_query(ib_portid_t * portid, int port, int mask)
517 common_func(portid, port, mask, !reset_only, (reset_only || reset),
518 "PortXmitDiscardDetails", IB_GSI_PORT_XMIT_DISCARD_DETAILS,
519 mad_dump_perfcounters_xmt_disc);
522 static void rcv_err_query(ib_portid_t * portid, int port, int mask)
524 common_func(portid, port, mask, !reset_only, (reset_only || reset),
525 "PortRcvErrorDetails", IB_GSI_PORT_RCV_ERROR_DETAILS,
526 mad_dump_perfcounters_rcv_err);
529 static uint8_t *ext_speeds_reset_via(void *rcvbuf, ib_portid_t * dest,
530 int port, uint64_t mask, unsigned timeout,
531 const struct ibmad_port * srcport)
533 ib_rpc_t rpc = { 0 };
536 DEBUG("lid %u port %d mask 0x%" PRIx64, lid, port, mask);
539 IBWARN("only lid routed is supported");
546 rpc.mgtclass = IB_PERFORMANCE_CLASS;
547 rpc.method = IB_MAD_METHOD_SET;
548 rpc.attr.id = IB_GSI_PORT_EXT_SPEEDS_COUNTERS;
550 memset(rcvbuf, 0, IB_MAD_SIZE);
552 mad_set_field(rcvbuf, 0, IB_PESC_PORT_SELECT_F, port);
553 mad_set_field64(rcvbuf, 0, IB_PESC_COUNTER_SELECT_F, mask);
555 rpc.timeout = timeout;
556 rpc.datasz = IB_PC_DATA_SZ;
557 rpc.dataoffs = IB_PC_DATA_OFFS;
561 dest->qkey = IB_DEFAULT_QP1_QKEY;
563 return mad_rpc(srcport, &rpc, dest, rcvbuf, rcvbuf);
566 static uint8_t is_rsfec_mode_active(ib_portid_t * portid, int port,
569 uint8_t data[IB_SMP_DATA_SIZE] = { 0 };
570 uint32_t fec_mode_active = 0;
571 uint32_t pie_capmask = 0;
572 if (cap_mask & IS_PM_RSFEC_COUNTERS_SUP) {
573 if (!is_port_info_extended_supported(portid, port, srcport)) {
574 IBWARN("Port Info Extended not supported");
578 if (!smp_query_via(data, portid, IB_ATTR_PORT_INFO_EXT, port, 0,
580 IBEXIT("smp query portinfo extended failed");
582 mad_decode_field(data, IB_PORT_EXT_CAPMASK_F, &pie_capmask);
583 mad_decode_field(data, IB_PORT_EXT_FEC_MODE_ACTIVE_F,
586 CL_NTOH32(IB_PORT_EXT_CAP_IS_FEC_MODE_SUPPORTED)) &&
587 (CL_NTOH16(IB_PORT_EXT_RS_FEC_MODE_ACTIVE) == (fec_mode_active & 0xffff)))
594 static void extended_speeds_query(ib_portid_t * portid, int port,
595 uint64_t ext_mask, uint16_t cap_mask)
600 if (is_rsfec_mode_active(portid, port, cap_mask))
601 common_func(portid, port, mask, 1, 0,
602 "PortExtendedSpeedsCounters with RS-FEC Active",
603 IB_GSI_PORT_EXT_SPEEDS_COUNTERS,
604 mad_dump_port_ext_speeds_counters_rsfec_active);
606 common_func(portid, port, mask, 1, 0,
607 "PortExtendedSpeedsCounters",
608 IB_GSI_PORT_EXT_SPEEDS_COUNTERS,
609 mad_dump_port_ext_speeds_counters);
612 if ((reset_only || reset) &&
613 !ext_speeds_reset_via(pc, portid, port, ext_mask, ibd_timeout, srcport))
614 IBEXIT("cannot reset PortExtendedSpeedsCounters");
617 static void oprcvcounters_query(ib_portid_t * portid, int port, int mask)
619 common_func(portid, port, mask, !reset_only, (reset_only || reset),
620 "PortOpRcvCounters", IB_GSI_PORT_PORT_OP_RCV_COUNTERS,
621 mad_dump_perfcounters_port_op_rcv_counters);
624 static void flowctlcounters_query(ib_portid_t * portid, int port, int mask)
626 common_func(portid, port, mask, !reset_only, (reset_only || reset),
627 "PortFlowCtlCounters", IB_GSI_PORT_PORT_FLOW_CTL_COUNTERS,
628 mad_dump_perfcounters_port_flow_ctl_counters);
631 static void vloppackets_query(ib_portid_t * portid, int port, int mask)
633 common_func(portid, port, mask, !reset_only, (reset_only || reset),
634 "PortVLOpPackets", IB_GSI_PORT_PORT_VL_OP_PACKETS,
635 mad_dump_perfcounters_port_vl_op_packet);
638 static void vlopdata_query(ib_portid_t * portid, int port, int mask)
640 common_func(portid, port, mask, !reset_only, (reset_only || reset),
641 "PortVLOpData", IB_GSI_PORT_PORT_VL_OP_DATA,
642 mad_dump_perfcounters_port_vl_op_data);
645 static void vlxmitflowctlerrors_query(ib_portid_t * portid, int port, int mask)
647 common_func(portid, port, mask, !reset_only, (reset_only || reset),
648 "PortVLXmitFlowCtlUpdateErrors", IB_GSI_PORT_PORT_VL_XMIT_FLOW_CTL_UPDATE_ERRORS,
649 mad_dump_perfcounters_port_vl_xmit_flow_ctl_update_errors);
652 static void vlxmitcounters_query(ib_portid_t * portid, int port, int mask)
654 common_func(portid, port, mask, !reset_only, (reset_only || reset),
655 "PortVLXmitWaitCounters", IB_GSI_PORT_PORT_VL_XMIT_WAIT_COUNTERS,
656 mad_dump_perfcounters_port_vl_xmit_wait_counters);
659 static void swportvlcong_query(ib_portid_t * portid, int port, int mask)
661 common_func(portid, port, mask, !reset_only, (reset_only || reset),
662 "SwPortVLCongestion", IB_GSI_SW_PORT_VL_CONGESTION,
663 mad_dump_perfcounters_sw_port_vl_congestion);
666 static void rcvcc_query(ib_portid_t * portid, int port, int mask)
668 common_func(portid, port, mask, !reset_only, (reset_only || reset),
669 "PortRcvConCtrl", IB_GSI_PORT_RCV_CON_CTRL,
670 mad_dump_perfcounters_rcv_con_ctrl);
673 static void slrcvfecn_query(ib_portid_t * portid, int port, int mask)
675 common_func(portid, port, mask, !reset_only, (reset_only || reset),
676 "PortSLRcvFECN", IB_GSI_PORT_SL_RCV_FECN,
677 mad_dump_perfcounters_sl_rcv_fecn);
680 static void slrcvbecn_query(ib_portid_t * portid, int port, int mask)
682 common_func(portid, port, mask, !reset_only, (reset_only || reset),
683 "PortSLRcvBECN", IB_GSI_PORT_SL_RCV_BECN,
684 mad_dump_perfcounters_sl_rcv_becn);
687 static void xmitcc_query(ib_portid_t * portid, int port, int mask)
689 common_func(portid, port, mask, !reset_only, (reset_only || reset),
690 "PortXmitConCtrl", IB_GSI_PORT_XMIT_CON_CTRL,
691 mad_dump_perfcounters_xmit_con_ctrl);
694 static void vlxmittimecc_query(ib_portid_t * portid, int port, int mask)
696 common_func(portid, port, mask, !reset_only, (reset_only || reset),
697 "PortVLXmitTimeCong", IB_GSI_PORT_VL_XMIT_TIME_CONG,
698 mad_dump_perfcounters_vl_xmit_time_cong);
701 void dump_portsamples_control(ib_portid_t * portid, int port)
705 memset(pc, 0, sizeof(pc));
706 if (!pma_query_via(pc, portid, port, ibd_timeout,
707 IB_GSI_PORT_SAMPLES_CONTROL, srcport))
708 IBEXIT("sampctlquery");
710 mad_dump_portsamples_control(buf, sizeof buf, pc, sizeof pc);
711 printf("# PortSamplesControl: %s port %d\n%s", portid2str(portid),
715 static int process_opt(void *context, int ch, char *optarg)
752 vlxmitflowctlerrors = 1;
789 if (!inet_pton(AF_INET6, optarg, &dgid)) {
790 fprintf(stderr, "dgid format is wrong!\n");
802 int main(int argc, char **argv)
804 int mgmt_classes[3] = { IB_SMI_CLASS, IB_SA_CLASS, IB_PERFORMANCE_CLASS };
805 ib_portid_t portid = { 0 };
807 uint64_t ext_mask = 0xffffffffffffffffULL;
810 int all_ports_loop = 0;
811 int node_type, num_ports = 0;
812 uint8_t data[IB_SMP_DATA_SIZE] = { 0 };
818 const struct ibdiag_opt opts[] = {
819 {"extended", 'x', 0, NULL, "show extended port counters"},
820 {"xmtsl", 'X', 0, NULL, "show Xmt SL port counters"},
821 {"rcvsl", 'S', 0, NULL, "show Rcv SL port counters"},
822 {"xmtdisc", 'D', 0, NULL, "show Xmt Discard Details"},
823 {"rcverr", 'E', 0, NULL, "show Rcv Error Details"},
824 {"extended_speeds", 'T', 0, NULL, "show port extended speeds counters"},
825 {"oprcvcounters", 1, 0, NULL, "show Rcv Counters per Op code"},
826 {"flowctlcounters", 2, 0, NULL, "show flow control counters"},
827 {"vloppackets", 3, 0, NULL, "show packets received per Op code per VL"},
828 {"vlopdata", 4, 0, NULL, "show data received per Op code per VL"},
829 {"vlxmitflowctlerrors", 5, 0, NULL, "show flow control update errors per VL"},
830 {"vlxmitcounters", 6, 0, NULL, "show ticks waiting to transmit counters per VL"},
831 {"swportvlcong", 7, 0, NULL, "show sw port VL congestion"},
832 {"rcvcc", 8, 0, NULL, "show Rcv congestion control counters"},
833 {"slrcvfecn", 9, 0, NULL, "show SL Rcv FECN counters"},
834 {"slrcvbecn", 10, 0, NULL, "show SL Rcv BECN counters"},
835 {"xmitcc", 11, 0, NULL, "show Xmit congestion control counters"},
836 {"vlxmittimecc", 12, 0, NULL, "show VL Xmit Time congestion control counters"},
837 {"smplctl", 'c', 0, NULL, "show samples control"},
838 {"all_ports", 'a', 0, NULL, "show aggregated counters"},
839 {"loop_ports", 'l', 0, NULL, "iterate through each port"},
840 {"reset_after_read", 'r', 0, NULL, "reset counters after read"},
841 {"Reset_only", 'R', 0, NULL, "only reset counters"},
842 {"dgid", 25, 1, NULL, "remote gid (IPv6 format)"},
845 char usage_args[] = " [<lid|guid> [[port(s)] [reset_mask]]]";
846 const char *usage_examples[] = {
847 "\t\t# read local port's performance counters",
848 "32 1\t\t# read performance counters from lid 32, port 1",
849 "-x 32 1\t# read extended performance counters from lid 32, port 1",
850 "-a 32\t\t# read performance counters from lid 32, all ports",
851 "-r 32 1\t# read performance counters and reset",
852 "-x -r 32 1\t# read extended performance counters and reset",
853 "-R 0x20 1\t# reset performance counters of port 1 only",
854 "-x -R 0x20 1\t# reset extended performance counters of port 1 only",
855 "-R -a 32\t# reset performance counters of all ports",
856 "-R 32 2 0x0fff\t# reset only error counters of port 2",
857 "-R 32 2 0xf000\t# reset only non-error counters of port 2",
858 "-a 32 1-10\t# read performance counters from lid 32, port 1-10, aggregate output",
859 "-l 32 1-10\t# read performance counters from lid 32, port 1-10, output each port",
860 "-a 32 1,4,8\t# read performance counters from lid 32, port 1, 4, and 8, aggregate output",
861 "-l 32 1,4,8\t# read performance counters from lid 32, port 1, 4, and 8, output each port",
865 ibdiag_process_opts(argc, argv, NULL, "DK", opts, process_opt,
866 usage_args, usage_examples);
872 if (strchr(argv[1], ',')) {
873 tmpstr = strtok(argv[1], ",");
875 ports[ports_count++] = strtoul(tmpstr, 0, 0);
876 tmpstr = strtok(NULL, ",");
880 else if ((tmpstr = strchr(argv[1], '-'))) {
886 pmin = strtoul(argv[1], 0, 0);
887 pmax = strtoul(tmpstr, 0, 0);
890 IBEXIT("max port must be greater than min port in range");
893 ports[ports_count++] = pmin++;
898 port = strtoul(argv[1], 0, 0);
901 ext_mask = strtoull(argv[2], 0, 0);
905 srcport = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 3);
907 IBEXIT("Failed to open '%s' port '%d'", ibd_ca, ibd_ca_port);
909 smp_mkey_set(srcport, ibd_mkey);
912 if (with_grh && ibd_dest_type != IB_DEST_LID)
913 IBEXIT("When using GRH, LID should be provided");
914 if (resolve_portid_str(ibd_ca, ibd_ca_port, &portid, argv[0],
915 ibd_dest_type, ibd_sm_id, srcport) < 0)
916 IBEXIT("can't resolve destination port %s", argv[0]);
918 portid.grh_present = 1;
919 memcpy(&portid.gid, &dgid, sizeof(portid.gid));
922 if (resolve_self(ibd_ca, ibd_ca_port, &portid, &port, 0) < 0)
923 IBEXIT("can't resolve self port %s", argv[0]);
926 /* PerfMgt ClassPortInfo is a required attribute */
927 memset(pc, 0, sizeof(pc));
928 if (!pma_query_via(pc, &portid, port, ibd_timeout, CLASS_PORT_INFO,
930 IBEXIT("classportinfo query");
931 /* ClassPortInfo should be supported as part of libibmad */
932 memcpy(&cap_mask, pc + 2, sizeof(cap_mask)); /* CapabilityMask */
933 memcpy(&cap_mask2, pc + 4, sizeof(cap_mask2)); /* CapabilityMask2 */
934 cap_mask2 = ntohl(cap_mask2) >> 5;
936 if (!(cap_mask & IB_PM_ALL_PORT_SELECT)) { /* bit 8 is AllPortSelect */
937 if (!all_ports && port == ALL_PORTS)
938 IBEXIT("AllPortSelect not supported");
939 if (all_ports && port == ALL_PORTS)
944 xmt_sl_query(&portid, port, mask);
949 rcv_sl_query(&portid, port, mask);
954 xmt_disc_query(&portid, port, mask);
959 rcv_err_query(&portid, port, mask);
963 if (extended_speeds) {
964 extended_speeds_query(&portid, port, ext_mask, cap_mask);
969 oprcvcounters_query(&portid, port, mask);
973 if (flowctlcounters) {
974 flowctlcounters_query(&portid, port, mask);
979 vloppackets_query(&portid, port, mask);
984 vlopdata_query(&portid, port, mask);
988 if (vlxmitflowctlerrors) {
989 vlxmitflowctlerrors_query(&portid, port, mask);
993 if (vlxmitcounters) {
994 vlxmitcounters_query(&portid, port, mask);
999 swportvlcong_query(&portid, port, mask);
1004 rcvcc_query(&portid, port, mask);
1009 slrcvfecn_query(&portid, port, mask);
1014 slrcvbecn_query(&portid, port, mask);
1019 xmitcc_query(&portid, port, mask);
1024 vlxmittimecc_query(&portid, port, mask);
1029 dump_portsamples_control(&portid, port);
1034 if (all_ports_loop || (loop_ports && (all_ports || port == ALL_PORTS))) {
1035 if (!smp_query_via(data, &portid, IB_ATTR_NODE_INFO, 0, 0,
1037 IBEXIT("smp query nodeinfo failed");
1038 node_type = mad_get_field(data, 0, IB_NODE_TYPE_F);
1039 mad_decode_field(data, IB_NODE_NPORTS_F, &num_ports);
1041 IBEXIT("smp query nodeinfo: num ports invalid");
1043 if (node_type == IB_NODE_SWITCH) {
1044 if (!smp_query_via(data, &portid, IB_ATTR_SWITCH_INFO,
1046 IBEXIT("smp query nodeinfo failed");
1048 mad_get_field(data, 0, IB_SW_ENHANCED_PORT0_F);
1052 if (all_ports_loop && !loop_ports)
1054 ("Emulating AllPortSelect by iterating through all ports");
1060 if (all_ports_loop || (loop_ports && (all_ports || port == ALL_PORTS))) {
1061 for (i = start_port; i <= num_ports; i++)
1062 dump_perfcounters(extended, ibd_timeout,
1063 cap_mask, cap_mask2,
1064 &portid, i, (all_ports_loop
1066 if (all_ports_loop && !loop_ports) {
1068 output_aggregate_perfcounters(&portid,
1071 output_aggregate_perfcounters_ext(&portid,
1072 cap_mask, cap_mask2);
1074 } else if (ports_count > 1) {
1075 for (i = 0; i < ports_count; i++)
1076 dump_perfcounters(extended, ibd_timeout, cap_mask,
1077 cap_mask2, &portid, ports[i],
1078 (all_ports && !loop_ports));
1079 if (all_ports && !loop_ports) {
1081 output_aggregate_perfcounters(&portid,
1084 output_aggregate_perfcounters_ext(&portid,
1085 cap_mask, cap_mask2);
1088 dump_perfcounters(extended, ibd_timeout, cap_mask, cap_mask2,
1095 if (argc <= 2 && !extended) {
1096 if (cap_mask & IB_PM_PC_XMIT_WAIT_SUP)
1097 mask |= (1 << 16); /* reset portxmitwait */
1098 if (cap_mask & IB_PM_IS_QP1_DROP_SUP)
1099 mask |= (1 << 17); /* reset qp1dropped */
1104 if (cap_mask & IB_PM_PC_XMIT_WAIT_SUP)
1106 if (cap_mask & IB_PM_IS_QP1_DROP_SUP)
1110 if (all_ports_loop || (loop_ports && (all_ports || port == ALL_PORTS))) {
1111 for (i = start_port; i <= num_ports; i++)
1112 reset_counters(extended, ibd_timeout, mask, &portid, i);
1113 } else if (ports_count > 1) {
1114 for (i = 0; i < ports_count; i++)
1115 reset_counters(extended, ibd_timeout, mask, &portid, ports[i]);
1117 reset_counters(extended, ibd_timeout, mask, &portid, port);
1120 mad_rpc_close_port(srcport);