]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - contrib/ofed/management/infiniband-diags/src/ibportstate.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 / ibportstate.c
1 /*
2  * Copyright (c) 2004-2008 Voltaire Inc.  All rights reserved.
3  *
4  * This software is available to you under a choice of one of two
5  * licenses.  You may choose to be licensed under the terms of the GNU
6  * General Public License (GPL) Version 2, available from the file
7  * COPYING in the main directory of this source tree, or the
8  * OpenIB.org BSD license below:
9  *
10  *     Redistribution and use in source and binary forms, with or
11  *     without modification, are permitted provided that the following
12  *     conditions are met:
13  *
14  *      - Redistributions of source code must retain the above
15  *        copyright notice, this list of conditions and the following
16  *        disclaimer.
17  *
18  *      - Redistributions in binary form must reproduce the above
19  *        copyright notice, this list of conditions and the following
20  *        disclaimer in the documentation and/or other materials
21  *        provided with the distribution.
22  *
23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30  * SOFTWARE.
31  *
32  */
33
34 #if HAVE_CONFIG_H
35 #  include <config.h>
36 #endif /* HAVE_CONFIG_H */
37
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <unistd.h>
41 #include <stdarg.h>
42 #include <time.h>
43 #include <string.h>
44 #include <getopt.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 #undef DEBUG
53 #define DEBUG   if (verbose>1) IBWARN
54
55 static int dest_type = IB_DEST_LID;
56 static int verbose;
57
58 char *argv0 = "ibportstate";
59
60 /*******************************************/
61
62 static int
63 get_node_info(ib_portid_t *dest, uint8_t *data)
64 {
65         int node_type;
66
67         if (!smp_query(data, dest, IB_ATTR_NODE_INFO, 0, 0))
68                 return -1;
69
70         node_type = mad_get_field(data, 0, IB_NODE_TYPE_F);
71         if (node_type == IB_NODE_SWITCH)        /* Switch NodeType ? */
72                 return 0;
73         else
74                 return 1;
75 }
76
77 static int
78 get_port_info(ib_portid_t *dest, uint8_t *data, int portnum, int port_op)
79 {
80         char buf[2048];
81         char val[64];
82
83         if (!smp_query(data, dest, IB_ATTR_PORT_INFO, portnum, 0))
84                 return -1;
85
86         if (port_op != 4) {
87                 mad_dump_portstates(buf, sizeof buf, data, sizeof data);
88                 mad_decode_field(data, IB_PORT_LINK_WIDTH_SUPPORTED_F, val);
89                 mad_dump_field(IB_PORT_LINK_WIDTH_SUPPORTED_F, buf + strlen(buf), sizeof buf - strlen(buf), val);
90                 sprintf(buf+strlen(buf), "%s", "\n");
91                 mad_decode_field(data, IB_PORT_LINK_WIDTH_ENABLED_F, val);
92                 mad_dump_field(IB_PORT_LINK_WIDTH_ENABLED_F, buf + strlen(buf), sizeof buf - strlen(buf), val);
93                 sprintf(buf+strlen(buf), "%s", "\n");
94                 mad_decode_field(data, IB_PORT_LINK_WIDTH_ACTIVE_F, val);
95                 mad_dump_field(IB_PORT_LINK_WIDTH_ACTIVE_F, buf + strlen(buf), sizeof buf - strlen(buf), val);
96                 sprintf(buf+strlen(buf), "%s", "\n");
97                 mad_decode_field(data, IB_PORT_LINK_SPEED_SUPPORTED_F, val);
98                 mad_dump_field(IB_PORT_LINK_SPEED_SUPPORTED_F, buf + strlen(buf), sizeof buf - strlen(buf), val);
99                 sprintf(buf+strlen(buf), "%s", "\n");
100                 mad_decode_field(data, IB_PORT_LINK_SPEED_ENABLED_F, val);
101                 mad_dump_field(IB_PORT_LINK_SPEED_ENABLED_F, buf + strlen(buf), sizeof buf - strlen(buf), val);
102                 sprintf(buf+strlen(buf), "%s", "\n");
103                 mad_decode_field(data, IB_PORT_LINK_SPEED_ACTIVE_F, val);
104                 mad_dump_field(IB_PORT_LINK_SPEED_ACTIVE_F, buf + strlen(buf), sizeof buf - strlen(buf), val);
105                 sprintf(buf+strlen(buf), "%s", "\n");
106         } else {
107                 mad_decode_field(data, IB_PORT_LINK_SPEED_ENABLED_F, val);
108                 mad_dump_field(IB_PORT_LINK_SPEED_ENABLED_F, buf, sizeof buf, val);
109                 sprintf(buf+strlen(buf), "%s", "\n");
110         }
111
112         printf("# Port info: %s port %d\n%s", portid2str(dest), portnum, buf);
113         return 0;
114 }
115
116 static int
117 set_port_info(ib_portid_t *dest, uint8_t *data, int portnum, int port_op)
118 {
119         char buf[2048];
120         char val[64];
121
122         if (!smp_set(data, dest, IB_ATTR_PORT_INFO, portnum, 0))
123                 return -1;
124
125         if (port_op != 4)
126                 mad_dump_portstates(buf, sizeof buf, data, sizeof data);
127         else {
128                 mad_decode_field(data, IB_PORT_LINK_SPEED_ENABLED_F, val);
129                 mad_dump_field(IB_PORT_LINK_SPEED_ENABLED_F, buf, sizeof buf, val);
130                 sprintf(buf+strlen(buf), "%s", "\n");
131         }
132
133         printf("\nAfter PortInfo set:\n");
134         printf("# Port info: %s port %d\n%s", portid2str(dest), portnum, buf);
135         return 0;
136 }
137
138 static int
139 get_link_width(int lwe, int lws)
140 {
141         if (lwe == 255)
142                 return lws;
143         else
144                 return lwe;
145 }
146
147 static int
148 get_link_speed(int lse, int lss)
149 {
150         if (lse == 15)
151                 return lss;
152         else
153                 return lse;
154 }
155
156 static void
157 validate_width(int width, int peerwidth, int lwa)
158 {
159         if ((width & 0x8) && (peerwidth & 0x8)) {
160                 if (lwa != 8)
161                         IBWARN("Peer ports operating at active width %d rather than 8 (12x)", lwa);
162         } else {
163                 if ((width & 0x4) && (peerwidth & 0x4)) {
164                         if (lwa != 4)
165                                 IBWARN("Peer ports operating at active width %d rather than 4 (8x)", lwa);
166                 } else {
167                         if ((width & 0x2) && (peerwidth & 0x2)) {
168                                 if (lwa != 2)
169                                         IBWARN("Peer ports operating at active width %d rather than 2 (4x)", lwa);
170                         } else {
171                                 if ((width & 0x1) && (peerwidth & 0x1)) {
172                                         if (lwa != 1)
173                                                 IBWARN("Peer ports operating at active width %d rather than 1 (1x)", lwa);
174                                 }
175                         }
176                 }
177         }
178 }
179
180 static void
181 validate_speed(int speed, int peerspeed, int lsa)
182 {
183         if ((speed & 0x4) && (peerspeed & 0x4)) {
184                 if (lsa != 4)
185                         IBWARN("Peer ports operating at active speed %d rather than  4 (10.0 Gbps)", lsa);
186         } else {
187                 if ((speed & 0x2) && (peerspeed & 0x2)) {
188                         if (lsa != 2)
189                                 IBWARN("Peer ports operating at active speed %d rather than 2 (5.0 Gbps)", lsa);
190                 } else {
191                         if ((speed & 0x1) && (peerspeed & 0x1)) {
192                                 if (lsa != 1)
193                                         IBWARN("Peer ports operating at active speed %d rather than 1 (2.5 Gbps)", lsa);
194                         }
195                 }
196         }
197 }
198
199 void
200 usage(void)
201 {
202         char *basename;
203
204         if (!(basename = strrchr(argv0, '/')))
205                 basename = argv0;
206         else
207                 basename++;
208
209         fprintf(stderr, "Usage: %s [-d(ebug) -e(rr_show) -v(erbose) -D(irect) -G(uid) -s smlid -V(ersion) -C ca_name -P ca_port "
210                         "-t(imeout) timeout_ms] <dest dr_path|lid|guid> <portnum> [<op>]\n",
211                         basename);
212         fprintf(stderr, "\tsupported ops: enable, disable, reset, speed, query\n");
213         fprintf(stderr, "\n\texamples:\n");
214         fprintf(stderr, "\t\t%s 3 1 disable\t\t\t# by lid\n", basename);
215         fprintf(stderr, "\t\t%s -G 0x2C9000100D051 1 enable\t# by guid\n", basename);
216         fprintf(stderr, "\t\t%s -D 0 1\t\t\t# (query) by direct route\n", basename);
217         fprintf(stderr, "\t\t%s 3 1 reset\t\t\t# by lid\n", basename);
218         fprintf(stderr, "\t\t%s 3 1 speed 1\t\t\t# by lid\n", basename);
219         exit(-1);
220 }
221
222 int
223 main(int argc, char **argv)
224 {
225         int mgmt_classes[3] = {IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS};
226         ib_portid_t portid = {0};
227         ib_portid_t *sm_id = 0, sm_portid = {0};
228         extern int ibdebug;
229         int err;
230         int timeout = 0, udebug = 0;
231         char *ca = 0;
232         int ca_port = 0;
233         int port_op = 0;        /* default to query */
234         int speed = 15;
235         int is_switch = 1;
236         int state, physstate, lwe, lws, lwa, lse, lss, lsa;
237         int peerlocalportnum, peerlwe, peerlws, peerlwa, peerlse, peerlss, peerlsa;
238         int width, peerwidth, peerspeed;
239         uint8_t data[IB_SMP_DATA_SIZE];
240         ib_portid_t peerportid = {0};
241         int portnum = 0;
242         ib_portid_t selfportid = {0};
243         int selfport = 0;
244
245         static char const str_opts[] = "C:P:t:s:devDGVhu";
246         static const struct option long_opts[] = {
247                 { "C", 1, 0, 'C'},
248                 { "P", 1, 0, 'P'},
249                 { "debug", 0, 0, 'd'},
250                 { "err_show", 0, 0, 'e'},
251                 { "verbose", 0, 0, 'v'},
252                 { "Direct", 0, 0, 'D'},
253                 { "Guid", 0, 0, 'G'},
254                 { "timeout", 1, 0, 't'},
255                 { "s", 1, 0, 's'},
256                 { "Version", 0, 0, 'V'},
257                 { "help", 0, 0, 'h'},
258                 { "usage", 0, 0, 'u'},
259                 { }
260         };
261
262         argv0 = argv[0];
263
264         while (1) {
265                 int ch = getopt_long(argc, argv, str_opts, long_opts, NULL);
266                 if ( ch == -1 )
267                         break;
268                 switch(ch) {
269                 case 'd':
270                         ibdebug++;
271                         madrpc_show_errors(1);
272                         umad_debug(udebug);
273                         udebug++;
274                         break;
275                 case 'e':
276                         madrpc_show_errors(1);
277                         break;
278                 case 'D':
279                         dest_type = IB_DEST_DRPATH;
280                         break;
281                 case 'G':
282                         dest_type = IB_DEST_GUID;
283                         break;
284                 case 'C':
285                         ca = optarg;
286                         break;
287                 case 'P':
288                         ca_port = strtoul(optarg, 0, 0);
289                         break;
290                 case 's':
291                         if (ib_resolve_portid_str(&sm_portid, optarg, IB_DEST_LID, 0) < 0)
292                                 IBERROR("can't resolve SM destination port %s", optarg);
293                         sm_id = &sm_portid;
294                         break;
295                 case 't':
296                         timeout = strtoul(optarg, 0, 0);
297                         madrpc_set_timeout(timeout);
298                         break;
299                 case 'v':
300                         verbose++;
301                         break;
302                 case 'V':
303                         fprintf(stderr, "%s %s\n", argv0, get_build_version() );
304                         exit(-1);
305                 default:
306                         usage();
307                         break;
308                 }
309         }
310         argc -= optind;
311         argv += optind;
312
313         if (argc < 2)
314                 usage();
315
316         madrpc_init(ca, ca_port, mgmt_classes, 3);
317
318         if (ib_resolve_portid_str(&portid, argv[0], dest_type, sm_id) < 0)
319                 IBERROR("can't resolve destination port %s", argv[0]);
320
321         /* First, make sure it is a switch port if it is a "set" */
322         if (argc >= 3) {
323                 if (!strcmp(argv[2], "enable"))
324                         port_op = 1;
325                 else if (!strcmp(argv[2], "disable"))
326                         port_op = 2;
327                 else if (!strcmp(argv[2], "reset"))
328                         port_op = 3;
329                 else if (!strcmp(argv[2], "speed")) {
330                         if (argc < 4)
331                                 IBERROR("speed requires an additional parameter");
332                         port_op = 4;
333                         /* Parse speed value */
334                         speed = strtoul(argv[3], 0, 0);
335                         if (speed > 15)
336                                 IBERROR("invalid speed value %d", speed);
337                 }
338         }
339
340         err = get_node_info(&portid, data);
341         if (err < 0)
342                 IBERROR("smp query nodeinfo failed");
343         if (err) {              /* not switch */
344                 if (port_op == 0)       /* query op */
345                         is_switch = 0;
346                 else if (port_op != 4)  /* other than speed op */
347                         IBERROR("smp query nodeinfo: Node type not switch");
348         }
349
350         if (argc-1 > 0)
351                 portnum = strtol(argv[1], 0, 0);
352
353         if (port_op)
354                 printf("Initial PortInfo:\n");
355         else
356                 printf("PortInfo:\n");
357         err = get_port_info(&portid, data, portnum, port_op);
358         if (err < 0)
359                 IBERROR("smp query portinfo failed");
360
361         /* Only if one of the "set" options is chosen */
362         if (port_op) {
363                 if (port_op == 1)               /* Enable port */
364                         mad_set_field(data, 0, IB_PORT_PHYS_STATE_F, 2);        /* Polling */
365                 else if ((port_op == 2) || (port_op == 3)) { /* Disable port */
366                         mad_set_field(data, 0, IB_PORT_STATE_F, 1);             /* Down */
367                         mad_set_field(data, 0, IB_PORT_PHYS_STATE_F, 3);        /* Disabled */
368                 } else if (port_op == 4) {      /* Set speed */
369                         mad_set_field(data, 0, IB_PORT_LINK_SPEED_ENABLED_F, speed);
370                         mad_set_field(data, 0, IB_PORT_STATE_F, 0);
371                         mad_set_field(data, 0, IB_PORT_PHYS_STATE_F, 0);
372                 }
373
374                 err = set_port_info(&portid, data, portnum, port_op);
375                 if (err < 0)
376                         IBERROR("smp set portinfo failed");
377
378                 if (port_op == 3) {     /* Reset port - so also enable */
379                         mad_set_field(data, 0, IB_PORT_PHYS_STATE_F, 2);        /* Polling */
380                         err = set_port_info(&portid, data, portnum, port_op);
381                         if (err < 0)
382                                 IBERROR("smp set portinfo failed");
383                 }
384         } else {        /* query op */
385                 /* only compare peer port if switch port */
386                 if (is_switch) {
387                         /* First, exclude SP0 */
388                         if (portnum) {
389                                 /* Now, make sure PortState is Active */
390                                 /* Or is PortPhysicalState LinkUp sufficient ? */
391                                 mad_decode_field(data, IB_PORT_STATE_F, &state);
392                                 mad_decode_field(data, IB_PORT_PHYS_STATE_F, &physstate);
393                                 if (state == 4) {       /* Active */
394                                         mad_decode_field(data, IB_PORT_LINK_WIDTH_ENABLED_F, &lwe );
395                                         mad_decode_field(data, IB_PORT_LINK_WIDTH_SUPPORTED_F, &lws);
396                                         mad_decode_field(data, IB_PORT_LINK_WIDTH_ACTIVE_F, &lwa);
397                                         mad_decode_field(data, IB_PORT_LINK_SPEED_SUPPORTED_F, &lss);
398                                         mad_decode_field(data, IB_PORT_LINK_SPEED_ACTIVE_F, &lsa);
399                                         mad_decode_field(data, IB_PORT_LINK_SPEED_ENABLED_F, &lse);
400
401                                         /* Setup portid for peer port */
402                                         memcpy(&peerportid, &portid, sizeof(peerportid));
403                                         peerportid.drpath.cnt = 1;
404                                         peerportid.drpath.p[1] = portnum;
405
406                                         /* Set DrSLID to local lid */
407                                         if (ib_resolve_self(&selfportid, &selfport, 0) < 0)
408                                                 IBERROR("could not resolve self");
409                                         peerportid.drpath.drslid = selfportid.lid;
410                                         peerportid.drpath.drdlid = 0xffff;
411
412                                         /* Get peer port NodeInfo to obtain peer port number */
413                                         err = get_node_info(&peerportid, data);
414                                         if (err < 0)
415                                                 IBERROR("smp query nodeinfo failed");
416
417                                         mad_decode_field(data, IB_NODE_LOCAL_PORT_F, &peerlocalportnum);
418
419                                         printf("Peer PortInfo:\n");
420                                         /* Get peer port characteristics */
421                                         err = get_port_info(&peerportid, data, peerlocalportnum, port_op);
422                                         if (err < 0)
423                                                 IBERROR("smp query peer portinfofailed");
424
425                                         mad_decode_field(data, IB_PORT_LINK_WIDTH_ENABLED_F, &peerlwe );
426                                         mad_decode_field(data, IB_PORT_LINK_WIDTH_SUPPORTED_F, &peerlws);
427                                         mad_decode_field(data, IB_PORT_LINK_WIDTH_ACTIVE_F, &peerlwa);
428                                         mad_decode_field(data, IB_PORT_LINK_SPEED_SUPPORTED_F, &peerlss);
429                                         mad_decode_field(data, IB_PORT_LINK_SPEED_ACTIVE_F, &peerlsa);
430                                         mad_decode_field(data, IB_PORT_LINK_SPEED_ENABLED_F, &peerlse);
431
432                                         /* Now validate peer port characteristics */
433                                         /* Examine Link Width */
434                                         width = get_link_width(lwe, lws);
435                                         peerwidth = get_link_width(peerlwe, peerlws);
436                                         validate_width(width, peerwidth, lwa);
437
438                                         /* Examine Link Speed */
439                                         speed = get_link_speed(lse, lss);
440                                         peerspeed = get_link_speed(peerlse, peerlss);
441                                         validate_speed(speed, peerspeed, lsa);
442                                 }
443                         }
444                 }
445         }
446
447         exit(0);
448 }