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