2 * Copyright (c) 2004-2008 Voltaire Inc. All rights reserved.
\r
3 * Copyright (c) 2007 Xsigo Systems Inc. All rights reserved.
\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
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
15 * - Redistributions of source code must retain the above
\r
16 * copyright notice, this list of conditions and the following
\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
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
36 # include <config.h>
\r
37 #endif /* HAVE_CONFIG_H */
\r
48 #include <inttypes.h>
\r
50 #include <infiniband/common.h>
\r
51 #include <infiniband/umad.h>
\r
52 #include <infiniband/mad.h>
\r
53 #include <infiniband/complib/cl_nodenamemap.h>
\r
55 #include "ibnetdiscover.h"
\r
56 #include "grouping.h"
\r
57 #include "ibdiag_common.h"
\r
59 static char *node_type_str[] = {
\r
67 static char *linkwidth_str[] = {
\r
79 static char *linkspeed_str[] = {
\r
87 static int timeout = 2000; /* ms */
\r
88 static int dumplevel = 0;
\r
92 char *argv0 = "ibnetdiscover";
\r
94 static char *node_name_map_file = NULL;
\r
95 static nn_map_t *node_name_map = NULL;
\r
97 Node *nodesdist[MAXHOPS+1]; /* last is Ca list */
\r
99 int maxhops_discovered = 0;
\r
101 struct ChassisList *chassis = NULL;
\r
104 get_linkwidth_str(int linkwidth)
\r
107 return linkwidth_str[0];
\r
109 return linkwidth_str[linkwidth];
\r
113 get_linkspeed_str(int linkspeed)
\r
116 return linkspeed_str[0];
\r
118 return linkspeed_str[linkspeed];
\r
121 static inline const char*
\r
122 node_type_str2(Node *node)
\r
124 switch(node->type) {
\r
125 case SWITCH_NODE: return "SW";
\r
126 case CA_NODE: return "CA";
\r
127 case ROUTER_NODE: return "RT";
\r
133 decode_port_info(void *pi, Port *port)
\r
135 mad_decode_field(pi, IB_PORT_LID_F, &port->lid);
\r
136 mad_decode_field(pi, IB_PORT_LMC_F, &port->lmc);
\r
137 mad_decode_field(pi, IB_PORT_STATE_F, &port->state);
\r
138 mad_decode_field(pi, IB_PORT_PHYS_STATE_F, &port->physstate);
\r
139 mad_decode_field(pi, IB_PORT_LINK_WIDTH_ACTIVE_F, &port->linkwidth);
\r
140 mad_decode_field(pi, IB_PORT_LINK_SPEED_ACTIVE_F, &port->linkspeed);
\r
145 get_port(Port *port, int portnum, ib_portid_t *portid)
\r
148 void *pi = portinfo;
\r
150 port->portnum = portnum;
\r
152 if (!smp_query(pi, portid, IB_ATTR_PORT_INFO, portnum, timeout))
\r
154 decode_port_info(pi, port);
\r
156 DEBUG("portid %s portnum %d: lid %d state %d physstate %d %s %s",
\r
157 portid2str(portid), portnum, port->lid, port->state, port->physstate, get_linkwidth_str(port->linkwidth), get_linkspeed_str(port->linkspeed));
\r
161 * Returns 0 if non switch node is found, 1 if switch is found, -1 if error.
\r
164 get_node(Node *node, Port *port, ib_portid_t *portid)
\r
167 char switchinfo[64];
\r
168 void *pi = portinfo, *ni = node->nodeinfo, *nd = node->nodedesc;
\r
169 void *si = switchinfo;
\r
171 if (!smp_query(ni, portid, IB_ATTR_NODE_INFO, 0, timeout))
\r
174 mad_decode_field(ni, IB_NODE_GUID_F, &node->nodeguid);
\r
175 mad_decode_field(ni, IB_NODE_TYPE_F, &node->type);
\r
176 mad_decode_field(ni, IB_NODE_NPORTS_F, &node->numports);
\r
177 mad_decode_field(ni, IB_NODE_DEVID_F, &node->devid);
\r
178 mad_decode_field(ni, IB_NODE_VENDORID_F, &node->vendid);
\r
179 mad_decode_field(ni, IB_NODE_SYSTEM_GUID_F, &node->sysimgguid);
\r
180 mad_decode_field(ni, IB_NODE_PORT_GUID_F, &node->portguid);
\r
181 mad_decode_field(ni, IB_NODE_LOCAL_PORT_F, &node->localport);
\r
182 port->portnum = node->localport;
\r
183 port->portguid = node->portguid;
\r
185 if (!smp_query(nd, portid, IB_ATTR_NODE_DESC, 0, timeout))
\r
188 if (!smp_query(pi, portid, IB_ATTR_PORT_INFO, 0, timeout))
\r
190 decode_port_info(pi, port);
\r
192 if (node->type != SWITCH_NODE)
\r
195 node->smalid = port->lid;
\r
196 node->smalmc = port->lmc;
\r
198 /* after we have the sma information find out the real PortInfo for this port */
\r
199 if (!smp_query(pi, portid, IB_ATTR_PORT_INFO, node->localport, timeout))
\r
201 decode_port_info(pi, port);
\r
203 if (!smp_query(si, portid, IB_ATTR_SWITCH_INFO, 0, timeout))
\r
204 node->smaenhsp0 = 0; /* assume base SP0 */
\r
206 mad_decode_field(si, IB_SW_ENHANCED_PORT0_F, &node->smaenhsp0);
\r
208 DEBUG("portid %s: got switch node %" PRIx64 " '%s'",
\r
209 portid2str(portid), node->nodeguid, node->nodedesc);
\r
214 extend_dpath(ib_dr_path_t *path, int nextport)
\r
216 if (path->cnt+2 >= sizeof(path->p))
\r
219 if (path->cnt > maxhops_discovered)
\r
220 maxhops_discovered = path->cnt;
\r
221 path->p[path->cnt] = nextport;
\r
226 dump_endnode(ib_portid_t *path, char *prompt, Node *node, Port *port)
\r
231 fprintf(f, "%s -> %s %s {%016" PRIx64 "} portnum %d lid %d-%d\"%s\"\n",
\r
232 portid2str(path), prompt,
\r
233 (node->type <= IB_NODE_MAX ? node_type_str[node->type] : "???"),
\r
234 node->nodeguid, node->type == SWITCH_NODE ? 0 : port->portnum,
\r
235 port->lid, port->lid + (1 << port->lmc) - 1,
\r
236 clean_nodedesc(node->nodedesc));
\r
239 #define HASHGUID(guid) ((uint32_t)(((uint32_t)(guid) * 101) ^ ((uint32_t)((guid) >> 32) * 103)))
\r
242 static Node *nodestbl[HTSZ];
\r
245 find_node(Node *new)
\r
247 int hash = HASHGUID(new->nodeguid) % HTSZ;
\r
250 for (node = nodestbl[hash]; node; node = node->htnext)
\r
251 if (node->nodeguid == new->nodeguid)
\r
258 create_node(Node *temp, ib_portid_t *path, int dist)
\r
261 int hash = HASHGUID(temp->nodeguid) % HTSZ;
\r
263 node = malloc(sizeof(*node));
\r
267 memcpy(node, temp, sizeof(*node));
\r
269 node->path = *path;
\r
271 node->htnext = nodestbl[hash];
\r
272 nodestbl[hash] = node;
\r
274 if (node->type != SWITCH_NODE)
\r
275 dist = MAXHOPS; /* special Ca list */
\r
277 node->dnext = nodesdist[dist];
\r
278 nodesdist[dist] = node;
\r
284 find_port(Node *node, Port *port)
\r
288 for (old = node->ports; old; old = old->next)
\r
289 if (old->portnum == port->portnum)
\r
296 create_port(Node *node, Port *temp)
\r
300 port = malloc(sizeof(*port));
\r
304 memcpy(port, temp, sizeof(*port));
\r
306 port->next = node->ports;
\r
307 node->ports = port;
\r
313 link_ports(Node *node, Port *port, Node *remotenode, Port *remoteport)
\r
315 DEBUG("linking: 0x%" PRIx64 " %p->%p:%u and 0x%" PRIx64 " %p->%p:%u",
\r
316 node->nodeguid, node, port, port->portnum,
\r
317 remotenode->nodeguid, remotenode, remoteport, remoteport->portnum);
\r
318 if (port->remoteport)
\r
319 port->remoteport->remoteport = NULL;
\r
320 if (remoteport->remoteport)
\r
321 remoteport->remoteport->remoteport = NULL;
\r
322 port->remoteport = remoteport;
\r
323 remoteport->remoteport = port;
\r
327 handle_port(Node *node, Port *port, ib_portid_t *path, int portnum, int dist)
\r
331 Node *remotenode, *oldnode;
\r
332 Port *remoteport, *oldport;
\r
334 memset(&node_buf, 0, sizeof(node_buf));
\r
335 memset(&port_buf, 0, sizeof(port_buf));
\r
337 DEBUG("handle node %p port %p:%d dist %d", node, port, portnum, dist);
\r
338 if (port->physstate != 5) /* LinkUp */
\r
341 if (extend_dpath(&path->drpath, portnum) < 0)
\r
344 if (get_node(&node_buf, &port_buf, path) < 0) {
\r
345 IBWARN("NodeInfo on %s failed, skipping port",
\r
347 path->drpath.cnt--; /* restore path */
\r
351 oldnode = find_node(&node_buf);
\r
353 remotenode = oldnode;
\r
354 else if (!(remotenode = create_node(&node_buf, path, dist + 1)))
\r
355 IBERROR("no memory");
\r
357 oldport = find_port(remotenode, &port_buf);
\r
359 remoteport = oldport;
\r
360 if (node != remotenode || port != remoteport)
\r
361 IBWARN("port moving...");
\r
362 } else if (!(remoteport = create_port(remotenode, &port_buf)))
\r
363 IBERROR("no memory");
\r
365 dump_endnode(path, oldnode ? "known remote" : "new remote",
\r
366 remotenode, remoteport);
\r
368 link_ports(node, port, remotenode, remoteport);
\r
370 path->drpath.cnt--; /* restore path */
\r
375 * Return 1 if found, 0 if not, -1 on errors.
\r
378 discover(ib_portid_t *from)
\r
388 DEBUG("from %s", portid2str(from));
\r
390 memset(&node_buf, 0, sizeof(node_buf));
\r
391 memset(&port_buf, 0, sizeof(port_buf));
\r
393 if (get_node(&node_buf, &port_buf, from) < 0) {
\r
394 IBWARN("can't reach node %s", portid2str(from));
\r
398 node = create_node(&node_buf, from, 0);
\r
400 IBERROR("out of memory");
\r
404 port = create_port(node, &port_buf);
\r
406 IBERROR("out of memory");
\r
408 if (node->type != SWITCH_NODE &&
\r
409 handle_port(node, port, from, node->localport, 0) < 0)
\r
412 for (dist = 0; dist < MAXHOPS; dist++) {
\r
414 for (node = nodesdist[dist]; node; node = node->dnext) {
\r
416 path = &node->path;
\r
418 DEBUG("dist %d node %p", dist, node);
\r
419 dump_endnode(path, "processing", node, port);
\r
421 for (i = 1; i <= node->numports; i++) {
\r
422 if (i == node->localport)
\r
425 if (get_port(&port_buf, i, path) < 0) {
\r
426 IBWARN("can't reach node %s port %d", portid2str(path), i);
\r
430 port = find_port(node, &port_buf);
\r
434 port = create_port(node, &port_buf);
\r
436 IBERROR("out of memory");
\r
438 /* If switch, set port GUID to node GUID */
\r
439 if (node->type == SWITCH_NODE)
\r
440 port->portguid = node->portguid;
\r
442 handle_port(node, port, path, i, dist);
\r
451 node_name(Node *node)
\r
453 static char buf[256];
\r
455 switch(node->type) {
\r
457 sprintf(buf, "\"%s", "S");
\r
460 sprintf(buf, "\"%s", "H");
\r
463 sprintf(buf, "\"%s", "R");
\r
466 sprintf(buf, "\"%s", "?");
\r
469 sprintf(buf+2, "-%016" PRIx64 "\"", node->nodeguid);
\r
475 list_node(Node *node)
\r
478 char *nodename = remap_node_name(node_name_map, node->nodeguid,
\r
481 switch(node->type) {
\r
483 node_type = "Switch";
\r
489 node_type = "Router";
\r
495 fprintf(f, "%s\t : 0x%016" PRIx64 " ports %d devid 0x%x vendid 0x%x \"%s\"\n",
\r
497 node->nodeguid, node->numports, node->devid, node->vendid,
\r
504 out_ids(Node *node, int group, char *chname)
\r
506 fprintf(f, "\nvendid=0x%x\ndevid=0x%x\n", node->vendid, node->devid);
\r
507 if (node->sysimgguid)
\r
508 fprintf(f, "sysimgguid=0x%" PRIx64, node->sysimgguid);
\r
510 && node->chrecord && node->chrecord->chassisnum) {
\r
511 fprintf(f, "\t\t# Chassis %d", node->chrecord->chassisnum);
\r
513 fprintf(f, " (%s)", chname);
\r
514 if (is_xsigo_tca(node->nodeguid) && node->ports->remoteport)
\r
515 fprintf(f, " slot %d", node->ports->remoteport->portnum);
\r
521 out_chassis(int chassisnum)
\r
525 fprintf(f, "\nChassis %d", chassisnum);
\r
526 guid = get_chassis_guid(chassisnum);
\r
528 fprintf(f, " (guid 0x%" PRIx64 ")", guid);
\r
534 out_switch(Node *node, int group, char *chname)
\r
537 char *nodename = NULL;
\r
539 out_ids(node, group, chname);
\r
540 fprintf(f, "switchguid=0x%" PRIx64, node->nodeguid);
\r
541 fprintf(f, "(%" PRIx64 ")", node->portguid);
\r
542 /* Currently, only if Voltaire chassis */
\r
544 && node->chrecord && node->chrecord->chassisnum
\r
545 && node->vendid == VTR_VENDOR_ID) {
\r
546 str = get_chassis_type(node->chrecord->chassistype);
\r
548 fprintf(f, "%s ", str);
\r
549 str = get_chassis_slot(node->chrecord->chassisslot);
\r
551 fprintf(f, "%s ", str);
\r
552 fprintf(f, "%d Chip %d", node->chrecord->slotnum, node->chrecord->anafanum);
\r
555 nodename = remap_node_name(node_name_map, node->nodeguid,
\r
558 fprintf(f, "\nSwitch\t%d %s\t\t# \"%s\" %s port 0 lid %d lmc %d\n",
\r
559 node->numports, node_name(node),
\r
561 node->smaenhsp0 ? "enhanced" : "base",
\r
562 node->smalid, node->smalmc);
\r
568 out_ca(Node *node, int group, char *chname)
\r
572 char *nodename = remap_node_name(node_name_map, node->nodeguid,
\r
575 out_ids(node, group, chname);
\r
576 switch(node->type) {
\r
587 node_type2 = "???";
\r
591 fprintf(f, "%sguid=0x%" PRIx64 "\n", node_type, node->nodeguid);
\r
592 fprintf(f, "%s\t%d %s\t\t# \"%s\"",
\r
593 node_type2, node->numports, node_name(node),
\r
595 if (group && is_xsigo_hca(node->nodeguid))
\r
596 fprintf(f, " (scp)");
\r
603 out_ext_port(Port *port, int group)
\r
607 /* Currently, only if Voltaire chassis */
\r
609 && port->node->chrecord && port->node->vendid == VTR_VENDOR_ID)
\r
610 str = portmapstring(port);
\r
616 out_switch_port(Port *port, int group)
\r
618 char *ext_port_str = NULL;
\r
619 char *rem_nodename = NULL;
\r
621 DEBUG("port %p:%d remoteport %p", port, port->portnum, port->remoteport);
\r
622 fprintf(f, "[%d]", port->portnum);
\r
624 ext_port_str = out_ext_port(port, group);
\r
626 fprintf(f, "%s", ext_port_str);
\r
628 rem_nodename = remap_node_name(node_name_map,
\r
629 port->remoteport->node->nodeguid,
\r
630 port->remoteport->node->nodedesc);
\r
632 ext_port_str = out_ext_port(port->remoteport, group);
\r
633 fprintf(f, "\t%s[%d]%s",
\r
634 node_name(port->remoteport->node),
\r
635 port->remoteport->portnum,
\r
636 ext_port_str ? ext_port_str : "");
\r
637 if (port->remoteport->node->type != SWITCH_NODE)
\r
638 fprintf(f, "(%" PRIx64 ") ", port->remoteport->portguid);
\r
639 fprintf(f, "\t\t# \"%s\" lid %d %s%s",
\r
641 port->remoteport->node->type == SWITCH_NODE ? port->remoteport->node->smalid : port->remoteport->lid,
\r
642 get_linkwidth_str(port->linkwidth),
\r
643 get_linkspeed_str(port->linkspeed));
\r
645 if (is_xsigo_tca(port->remoteport->portguid))
\r
646 fprintf(f, " slot %d", port->portnum);
\r
647 else if (is_xsigo_hca(port->remoteport->portguid))
\r
648 fprintf(f, " (scp)");
\r
651 free(rem_nodename);
\r
655 out_ca_port(Port *port, int group)
\r
658 char *rem_nodename = NULL;
\r
660 fprintf(f, "[%d]", port->portnum);
\r
661 if (port->node->type != SWITCH_NODE)
\r
662 fprintf(f, "(%" PRIx64 ") ", port->portguid);
\r
663 fprintf(f, "\t%s[%d]",
\r
664 node_name(port->remoteport->node),
\r
665 port->remoteport->portnum);
\r
666 str = out_ext_port(port->remoteport, group);
\r
668 fprintf(f, "%s", str);
\r
669 if (port->remoteport->node->type != SWITCH_NODE)
\r
670 fprintf(f, " (%" PRIx64 ") ", port->remoteport->portguid);
\r
672 rem_nodename = remap_node_name(node_name_map,
\r
673 port->remoteport->node->nodeguid,
\r
674 port->remoteport->node->nodedesc);
\r
676 fprintf(f, "\t\t# lid %d lmc %d \"%s\" lid %d %s%s\n",
\r
677 port->lid, port->lmc, rem_nodename,
\r
678 port->remoteport->node->type == SWITCH_NODE ? port->remoteport->node->smalid : port->remoteport->lid,
\r
679 get_linkwidth_str(port->linkwidth),
\r
680 get_linkspeed_str(port->linkspeed));
\r
682 free(rem_nodename);
\r
686 dump_topology(int listtype, int group)
\r
690 int i = 0, dist = 0;
\r
691 time_t t = time(0);
\r
693 char *chname = NULL;
\r
696 fprintf(f, "#\n# Topology file: generated on %s#\n", ctime(&t));
\r
697 fprintf(f, "# Max of %d hops discovered\n", maxhops_discovered);
\r
698 fprintf(f, "# Initiated from node %016" PRIx64 " port %016" PRIx64 "\n", mynode->nodeguid, mynode->portguid);
\r
701 /* Make pass on switches */
\r
702 if (group && !listtype) {
\r
703 ChassisList *ch = NULL;
\r
705 /* Chassis based switches first */
\r
706 for (ch = chassis; ch; ch = ch->next) {
\r
709 if (!ch->chassisnum)
\r
711 chguid = out_chassis(ch->chassisnum);
\r
715 if (is_xsigo_guid(chguid)) {
\r
716 for (node = nodesdist[MAXHOPS]; node; node = node->dnext) {
\r
717 if (!node->chrecord ||
\r
718 !node->chrecord->chassisnum)
\r
721 if (node->chrecord->chassisnum != ch->chassisnum)
\r
724 if (is_xsigo_hca(node->nodeguid)) {
\r
725 chname = remap_node_name(node_name_map,
\r
728 fprintf(f, "Hostname: %s\n", chname);
\r
733 fprintf(f, "\n# Spine Nodes");
\r
734 for (n = 1; n <= (SPINES_MAX_NUM+1); n++) {
\r
735 if (ch->spinenode[n]) {
\r
736 out_switch(ch->spinenode[n], group, chname);
\r
737 for (port = ch->spinenode[n]->ports; port; port = port->next, i++)
\r
738 if (port->remoteport)
\r
739 out_switch_port(port, group);
\r
742 fprintf(f, "\n# Line Nodes");
\r
743 for (n = 1; n <= (LINES_MAX_NUM+1); n++) {
\r
744 if (ch->linenode[n]) {
\r
745 out_switch(ch->linenode[n], group, chname);
\r
746 for (port = ch->linenode[n]->ports; port; port = port->next, i++)
\r
747 if (port->remoteport)
\r
748 out_switch_port(port, group);
\r
752 fprintf(f, "\n# Chassis Switches");
\r
753 for (dist = 0; dist <= maxhops_discovered; dist++) {
\r
755 for (node = nodesdist[dist]; node; node = node->dnext) {
\r
757 /* Non Voltaire chassis */
\r
758 if (node->vendid == VTR_VENDOR_ID)
\r
760 if (!node->chrecord ||
\r
761 !node->chrecord->chassisnum)
\r
764 if (node->chrecord->chassisnum != ch->chassisnum)
\r
767 out_switch(node, group, chname);
\r
768 for (port = node->ports; port; port = port->next, i++)
\r
769 if (port->remoteport)
\r
770 out_switch_port(port, group);
\r
776 fprintf(f, "\n# Chassis CAs");
\r
777 for (node = nodesdist[MAXHOPS]; node; node = node->dnext) {
\r
778 if (!node->chrecord ||
\r
779 !node->chrecord->chassisnum)
\r
782 if (node->chrecord->chassisnum != ch->chassisnum)
\r
785 out_ca(node, group, chname);
\r
786 for (port = node->ports; port; port = port->next, i++)
\r
787 if (port->remoteport)
\r
788 out_ca_port(port, group);
\r
795 for (dist = 0; dist <= maxhops_discovered; dist++) {
\r
797 for (node = nodesdist[dist]; node; node = node->dnext) {
\r
799 DEBUG("SWITCH: dist %d node %p", dist, node);
\r
801 out_switch(node, group, chname);
\r
803 if (listtype & LIST_SWITCH_NODE)
\r
808 for (port = node->ports; port; port = port->next, i++)
\r
809 if (port->remoteport)
\r
810 out_switch_port(port, group);
\r
818 if (group && !listtype) {
\r
820 fprintf(f, "\nNon-Chassis Nodes\n");
\r
822 for (dist = 0; dist <= maxhops_discovered; dist++) {
\r
824 for (node = nodesdist[dist]; node; node = node->dnext) {
\r
826 DEBUG("SWITCH: dist %d node %p", dist, node);
\r
827 /* Now, skip chassis based switches */
\r
828 if (node->chrecord &&
\r
829 node->chrecord->chassisnum)
\r
831 out_switch(node, group, chname);
\r
833 for (port = node->ports; port; port = port->next, i++)
\r
834 if (port->remoteport)
\r
835 out_switch_port(port, group);
\r
842 /* Make pass on CAs */
\r
843 for (node = nodesdist[MAXHOPS]; node; node = node->dnext) {
\r
845 DEBUG("CA: dist %d node %p", dist, node);
\r
847 /* Now, skip chassis based CAs */
\r
848 if (group && node->chrecord &&
\r
849 node->chrecord->chassisnum)
\r
851 out_ca(node, group, chname);
\r
853 if (((listtype & LIST_CA_NODE) && (node->type == CA_NODE)) ||
\r
854 ((listtype & LIST_ROUTER_NODE) && (node->type == ROUTER_NODE)))
\r
859 for (port = node->ports; port; port = port->next, i++)
\r
860 if (port->remoteport)
\r
861 out_ca_port(port, group);
\r
870 void dump_ports_report ()
\r
876 // If switch and LID == 0, search of other switch ports with
\r
877 // valid LID and assign it to all ports of that switch
\r
878 for (b = 0; b <= MAXHOPS; b++)
\r
879 for (node = nodesdist[b]; node; node = node->dnext)
\r
880 if (node->type == SWITCH_NODE) {
\r
882 for (p = 0, port = node->ports;
\r
883 p < node->numports && port && !swlid;
\r
885 if (port->lid != 0)
\r
887 for (p = 0, port = node->ports;
\r
888 p < node->numports && port;
\r
893 for (b = 0; b <= MAXHOPS; b++)
\r
894 for (node = nodesdist[b]; node; node = node->dnext) {
\r
895 for (p = 0, port = node->ports;
\r
896 p < node->numports && port;
\r
897 p++, port = port->next) {
\r
899 "%2s %5d %2d 0x%016" PRIx64 " %s %s",
\r
900 node_type_str2(port->node), port->lid,
\r
903 get_linkwidth_str(port->linkwidth),
\r
904 get_linkspeed_str(port->linkspeed));
\r
905 if (port->remoteport)
\r
907 " - %2s %5d %2d 0x%016" PRIx64
\r
908 " ( '%s' - '%s' )\n",
\r
909 node_type_str2(port->remoteport->node),
\r
910 port->remoteport->lid,
\r
911 port->remoteport->portnum,
\r
912 port->remoteport->portguid,
\r
913 port->node->nodedesc,
\r
914 port->remoteport->node->nodedesc);
\r
916 fprintf(stdout, "%36s'%s'\n", "",
\r
917 port->node->nodedesc);
\r
926 fprintf(stderr, "Usage: %s [-d(ebug)] -e(rr_show) -v(erbose) -s(how) -l(ist) -g(rouping) -H(ca_list) -S(witch_list) -R(outer_list) -V(ersion) -C ca_name -P ca_port "
\r
927 "-t(imeout) timeout_ms --node-name-map node-name-map] -p(orts) [<topology-file>]\n",
\r
929 fprintf(stderr, " --node-name-map <node-name-map> specify a node name map file\n");
\r
934 main(int argc, char **argv)
\r
936 int mgmt_classes[2] = {IB_SMI_CLASS, IB_SMI_DIRECT_CLASS};
\r
937 ib_portid_t my_portid = {0};
\r
938 int udebug = 0, list = 0;
\r
942 int ports_report = 0;
\r
944 static char const str_opts[] = "C:P:t:devslgHSRpVhu";
\r
945 static const struct option long_opts[] = {
\r
948 { "debug", 0, 0, 'd'},
\r
949 { "err_show", 0, 0, 'e'},
\r
950 { "verbose", 0, 0, 'v'},
\r
951 { "show", 0, 0, 's'},
\r
952 { "list", 0, 0, 'l'},
\r
953 { "grouping", 0, 0, 'g'},
\r
954 { "Hca_list", 0, 0, 'H'},
\r
955 { "Switch_list", 0, 0, 'S'},
\r
956 { "Router_list", 0, 0, 'R'},
\r
957 { "timeout", 1, 0, 't'},
\r
958 { "node-name-map", 1, 0, 1},
\r
959 { "ports", 0, 0, 'p'},
\r
960 { "Version", 0, 0, 'V'},
\r
961 { "help", 0, 0, 'h'},
\r
962 { "usage", 0, 0, 'u'},
\r
971 int ch = getopt_long(argc, argv, str_opts, long_opts, NULL);
\r
976 node_name_map_file = strdup(optarg);
\r
982 ca_port = strtoul(optarg, 0, 0);
\r
986 madrpc_show_errors(1);
\r
987 umad_debug(udebug);
\r
991 timeout = strtoul(optarg, 0, 0);
\r
1001 madrpc_show_errors(1);
\r
1004 list = LIST_CA_NODE | LIST_SWITCH_NODE | LIST_ROUTER_NODE;
\r
1010 list = LIST_SWITCH_NODE;
\r
1013 list = LIST_CA_NODE;
\r
1016 list = LIST_ROUTER_NODE;
\r
1019 fprintf(stderr, "%s %s\n", argv0, get_build_version() );
\r
1032 if (argc && !(f = fopen(argv[0], "w")))
\r
1033 IBERROR("can't open file %s for writing", argv[0]);
\r
1035 madrpc_init(ca, ca_port, mgmt_classes, 2);
\r
1036 node_name_map = open_node_name_map(node_name_map_file);
\r
1038 if (discover(&my_portid) < 0)
\r
1039 IBERROR("discover");
\r
1042 chassis = group_nodes();
\r
1045 dump_ports_report();
\r
1047 dump_topology(list, group);
\r
1049 close_node_name_map(node_name_map);
\r