1219820Sjeff/* 2219820Sjeff * Copyright (c) 2004-2008 Voltaire Inc. All rights reserved. 3219820Sjeff * Copyright (c) 2007 Xsigo Systems Inc. All rights reserved. 4219820Sjeff * 5219820Sjeff * This software is available to you under a choice of one of two 6219820Sjeff * licenses. You may choose to be licensed under the terms of the GNU 7219820Sjeff * General Public License (GPL) Version 2, available from the file 8219820Sjeff * COPYING in the main directory of this source tree, or the 9219820Sjeff * OpenIB.org BSD license below: 10219820Sjeff * 11219820Sjeff * Redistribution and use in source and binary forms, with or 12219820Sjeff * without modification, are permitted provided that the following 13219820Sjeff * conditions are met: 14219820Sjeff * 15219820Sjeff * - Redistributions of source code must retain the above 16219820Sjeff * copyright notice, this list of conditions and the following 17219820Sjeff * disclaimer. 18219820Sjeff * 19219820Sjeff * - Redistributions in binary form must reproduce the above 20219820Sjeff * copyright notice, this list of conditions and the following 21219820Sjeff * disclaimer in the documentation and/or other materials 22219820Sjeff * provided with the distribution. 23219820Sjeff * 24219820Sjeff * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 25219820Sjeff * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 26219820Sjeff * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 27219820Sjeff * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 28219820Sjeff * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 29219820Sjeff * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 30219820Sjeff * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31219820Sjeff * SOFTWARE. 32219820Sjeff * 33219820Sjeff */ 34219820Sjeff 35219820Sjeff#if HAVE_CONFIG_H 36219820Sjeff# include <config.h> 37219820Sjeff#endif /* HAVE_CONFIG_H */ 38219820Sjeff 39219820Sjeff#define _GNU_SOURCE 40219820Sjeff#include <stdio.h> 41219820Sjeff#include <stdlib.h> 42219820Sjeff#include <unistd.h> 43219820Sjeff#include <stdarg.h> 44219820Sjeff#include <time.h> 45219820Sjeff#include <string.h> 46219820Sjeff#include <getopt.h> 47219820Sjeff#include <errno.h> 48219820Sjeff#include <inttypes.h> 49219820Sjeff 50219820Sjeff#include <infiniband/common.h> 51219820Sjeff#include <infiniband/umad.h> 52219820Sjeff#include <infiniband/mad.h> 53219820Sjeff#include <infiniband/complib/cl_nodenamemap.h> 54219820Sjeff 55219820Sjeff#include "ibnetdiscover.h" 56219820Sjeff#include "grouping.h" 57219820Sjeff#include "ibdiag_common.h" 58219820Sjeff 59219820Sjeffstatic char *node_type_str[] = { 60219820Sjeff "???", 61219820Sjeff "ca", 62219820Sjeff "switch", 63219820Sjeff "router", 64219820Sjeff "iwarp rnic" 65219820Sjeff}; 66219820Sjeff 67219820Sjeffstatic char *linkwidth_str[] = { 68219820Sjeff "??", 69219820Sjeff "1x", 70219820Sjeff "4x", 71219820Sjeff "??", 72219820Sjeff "8x", 73219820Sjeff "??", 74219820Sjeff "??", 75219820Sjeff "??", 76219820Sjeff "12x" 77219820Sjeff}; 78219820Sjeff 79219820Sjeffstatic char *linkspeed_str[] = { 80219820Sjeff "???", 81219820Sjeff "SDR", 82219820Sjeff "DDR", 83219820Sjeff "???", 84219820Sjeff "QDR" 85219820Sjeff}; 86219820Sjeff 87219820Sjeffstatic int timeout = 2000; /* ms */ 88219820Sjeffstatic int dumplevel = 0; 89219820Sjeffstatic int verbose; 90219820Sjeffstatic FILE *f; 91219820Sjeff 92219820Sjeffchar *argv0 = "ibnetdiscover"; 93219820Sjeff 94219820Sjeffstatic char *node_name_map_file = NULL; 95219820Sjeffstatic nn_map_t *node_name_map = NULL; 96219820Sjeff 97219820SjeffNode *nodesdist[MAXHOPS+1]; /* last is Ca list */ 98219820SjeffNode *mynode; 99219820Sjeffint maxhops_discovered = 0; 100219820Sjeff 101219820Sjeffstruct ChassisList *chassis = NULL; 102219820Sjeff 103219820Sjeffstatic char * 104219820Sjeffget_linkwidth_str(int linkwidth) 105219820Sjeff{ 106219820Sjeff if (linkwidth > 8) 107219820Sjeff return linkwidth_str[0]; 108219820Sjeff else 109219820Sjeff return linkwidth_str[linkwidth]; 110219820Sjeff} 111219820Sjeff 112219820Sjeffstatic char * 113219820Sjeffget_linkspeed_str(int linkspeed) 114219820Sjeff{ 115219820Sjeff if (linkspeed > 4) 116219820Sjeff return linkspeed_str[0]; 117219820Sjeff else 118219820Sjeff return linkspeed_str[linkspeed]; 119219820Sjeff} 120219820Sjeff 121219820Sjeffstatic inline const char* 122219820Sjeffnode_type_str2(Node *node) 123219820Sjeff{ 124219820Sjeff switch(node->type) { 125219820Sjeff case SWITCH_NODE: return "SW"; 126219820Sjeff case CA_NODE: return "CA"; 127219820Sjeff case ROUTER_NODE: return "RT"; 128219820Sjeff } 129219820Sjeff return "??"; 130219820Sjeff} 131219820Sjeff 132219820Sjeffvoid 133219820Sjeffdecode_port_info(void *pi, Port *port) 134219820Sjeff{ 135219820Sjeff mad_decode_field(pi, IB_PORT_LID_F, &port->lid); 136219820Sjeff mad_decode_field(pi, IB_PORT_LMC_F, &port->lmc); 137219820Sjeff mad_decode_field(pi, IB_PORT_STATE_F, &port->state); 138219820Sjeff mad_decode_field(pi, IB_PORT_PHYS_STATE_F, &port->physstate); 139219820Sjeff mad_decode_field(pi, IB_PORT_LINK_WIDTH_ACTIVE_F, &port->linkwidth); 140219820Sjeff mad_decode_field(pi, IB_PORT_LINK_SPEED_ACTIVE_F, &port->linkspeed); 141219820Sjeff} 142219820Sjeff 143219820Sjeff 144219820Sjeffint 145219820Sjeffget_port(Port *port, int portnum, ib_portid_t *portid) 146219820Sjeff{ 147219820Sjeff char portinfo[64]; 148219820Sjeff void *pi = portinfo; 149219820Sjeff 150219820Sjeff port->portnum = portnum; 151219820Sjeff 152219820Sjeff if (!smp_query(pi, portid, IB_ATTR_PORT_INFO, portnum, timeout)) 153219820Sjeff return -1; 154219820Sjeff decode_port_info(pi, port); 155219820Sjeff 156219820Sjeff DEBUG("portid %s portnum %d: lid %d state %d physstate %d %s %s", 157219820Sjeff portid2str(portid), portnum, port->lid, port->state, port->physstate, get_linkwidth_str(port->linkwidth), get_linkspeed_str(port->linkspeed)); 158219820Sjeff return 1; 159219820Sjeff} 160219820Sjeff/* 161219820Sjeff * Returns 0 if non switch node is found, 1 if switch is found, -1 if error. 162219820Sjeff */ 163219820Sjeffint 164219820Sjeffget_node(Node *node, Port *port, ib_portid_t *portid) 165219820Sjeff{ 166219820Sjeff char portinfo[64]; 167219820Sjeff char switchinfo[64]; 168219820Sjeff void *pi = portinfo, *ni = node->nodeinfo, *nd = node->nodedesc; 169219820Sjeff void *si = switchinfo; 170219820Sjeff 171219820Sjeff if (!smp_query(ni, portid, IB_ATTR_NODE_INFO, 0, timeout)) 172219820Sjeff return -1; 173219820Sjeff 174219820Sjeff mad_decode_field(ni, IB_NODE_GUID_F, &node->nodeguid); 175219820Sjeff mad_decode_field(ni, IB_NODE_TYPE_F, &node->type); 176219820Sjeff mad_decode_field(ni, IB_NODE_NPORTS_F, &node->numports); 177219820Sjeff mad_decode_field(ni, IB_NODE_DEVID_F, &node->devid); 178219820Sjeff mad_decode_field(ni, IB_NODE_VENDORID_F, &node->vendid); 179219820Sjeff mad_decode_field(ni, IB_NODE_SYSTEM_GUID_F, &node->sysimgguid); 180219820Sjeff mad_decode_field(ni, IB_NODE_PORT_GUID_F, &node->portguid); 181219820Sjeff mad_decode_field(ni, IB_NODE_LOCAL_PORT_F, &node->localport); 182219820Sjeff port->portnum = node->localport; 183219820Sjeff port->portguid = node->portguid; 184219820Sjeff 185219820Sjeff if (!smp_query(nd, portid, IB_ATTR_NODE_DESC, 0, timeout)) 186219820Sjeff return -1; 187219820Sjeff 188219820Sjeff if (!smp_query(pi, portid, IB_ATTR_PORT_INFO, 0, timeout)) 189219820Sjeff return -1; 190219820Sjeff decode_port_info(pi, port); 191219820Sjeff 192219820Sjeff if (node->type != SWITCH_NODE) 193219820Sjeff return 0; 194219820Sjeff 195219820Sjeff node->smalid = port->lid; 196219820Sjeff node->smalmc = port->lmc; 197219820Sjeff 198219820Sjeff /* after we have the sma information find out the real PortInfo for this port */ 199219820Sjeff if (!smp_query(pi, portid, IB_ATTR_PORT_INFO, node->localport, timeout)) 200219820Sjeff return -1; 201219820Sjeff decode_port_info(pi, port); 202219820Sjeff 203219820Sjeff if (!smp_query(si, portid, IB_ATTR_SWITCH_INFO, 0, timeout)) 204219820Sjeff node->smaenhsp0 = 0; /* assume base SP0 */ 205219820Sjeff else 206219820Sjeff mad_decode_field(si, IB_SW_ENHANCED_PORT0_F, &node->smaenhsp0); 207219820Sjeff 208219820Sjeff DEBUG("portid %s: got switch node %" PRIx64 " '%s'", 209219820Sjeff portid2str(portid), node->nodeguid, node->nodedesc); 210219820Sjeff return 1; 211219820Sjeff} 212219820Sjeff 213219820Sjeffstatic int 214219820Sjeffextend_dpath(ib_dr_path_t *path, int nextport) 215219820Sjeff{ 216219820Sjeff if (path->cnt+2 >= sizeof(path->p)) 217219820Sjeff return -1; 218219820Sjeff ++path->cnt; 219219820Sjeff if (path->cnt > maxhops_discovered) 220219820Sjeff maxhops_discovered = path->cnt; 221219820Sjeff path->p[path->cnt] = nextport; 222219820Sjeff return path->cnt; 223219820Sjeff} 224219820Sjeff 225219820Sjeffstatic void 226219820Sjeffdump_endnode(ib_portid_t *path, char *prompt, Node *node, Port *port) 227219820Sjeff{ 228219820Sjeff if (!dumplevel) 229219820Sjeff return; 230219820Sjeff 231219820Sjeff fprintf(f, "%s -> %s %s {%016" PRIx64 "} portnum %d lid %d-%d\"%s\"\n", 232219820Sjeff portid2str(path), prompt, 233219820Sjeff (node->type <= IB_NODE_MAX ? node_type_str[node->type] : "???"), 234219820Sjeff node->nodeguid, node->type == SWITCH_NODE ? 0 : port->portnum, 235219820Sjeff port->lid, port->lid + (1 << port->lmc) - 1, 236219820Sjeff clean_nodedesc(node->nodedesc)); 237219820Sjeff} 238219820Sjeff 239219820Sjeff#define HASHGUID(guid) ((uint32_t)(((uint32_t)(guid) * 101) ^ ((uint32_t)((guid) >> 32) * 103))) 240219820Sjeff#define HTSZ 137 241219820Sjeff 242219820Sjeffstatic Node *nodestbl[HTSZ]; 243219820Sjeff 244219820Sjeffstatic Node * 245219820Sjefffind_node(Node *new) 246219820Sjeff{ 247219820Sjeff int hash = HASHGUID(new->nodeguid) % HTSZ; 248219820Sjeff Node *node; 249219820Sjeff 250219820Sjeff for (node = nodestbl[hash]; node; node = node->htnext) 251219820Sjeff if (node->nodeguid == new->nodeguid) 252219820Sjeff return node; 253219820Sjeff 254219820Sjeff return NULL; 255219820Sjeff} 256219820Sjeff 257219820Sjeffstatic Node * 258219820Sjeffcreate_node(Node *temp, ib_portid_t *path, int dist) 259219820Sjeff{ 260219820Sjeff Node *node; 261219820Sjeff int hash = HASHGUID(temp->nodeguid) % HTSZ; 262219820Sjeff 263219820Sjeff node = malloc(sizeof(*node)); 264219820Sjeff if (!node) 265219820Sjeff return NULL; 266219820Sjeff 267219820Sjeff memcpy(node, temp, sizeof(*node)); 268219820Sjeff node->dist = dist; 269219820Sjeff node->path = *path; 270219820Sjeff 271219820Sjeff node->htnext = nodestbl[hash]; 272219820Sjeff nodestbl[hash] = node; 273219820Sjeff 274219820Sjeff if (node->type != SWITCH_NODE) 275219820Sjeff dist = MAXHOPS; /* special Ca list */ 276219820Sjeff 277219820Sjeff node->dnext = nodesdist[dist]; 278219820Sjeff nodesdist[dist] = node; 279219820Sjeff 280219820Sjeff return node; 281219820Sjeff} 282219820Sjeff 283219820Sjeffstatic Port * 284219820Sjefffind_port(Node *node, Port *port) 285219820Sjeff{ 286219820Sjeff Port *old; 287219820Sjeff 288219820Sjeff for (old = node->ports; old; old = old->next) 289219820Sjeff if (old->portnum == port->portnum) 290219820Sjeff return old; 291219820Sjeff 292219820Sjeff return NULL; 293219820Sjeff} 294219820Sjeff 295219820Sjeffstatic Port * 296219820Sjeffcreate_port(Node *node, Port *temp) 297219820Sjeff{ 298219820Sjeff Port *port; 299219820Sjeff 300219820Sjeff port = malloc(sizeof(*port)); 301219820Sjeff if (!port) 302219820Sjeff return NULL; 303219820Sjeff 304219820Sjeff memcpy(port, temp, sizeof(*port)); 305219820Sjeff port->node = node; 306219820Sjeff port->next = node->ports; 307219820Sjeff node->ports = port; 308219820Sjeff 309219820Sjeff return port; 310219820Sjeff} 311219820Sjeff 312219820Sjeffstatic void 313219820Sjefflink_ports(Node *node, Port *port, Node *remotenode, Port *remoteport) 314219820Sjeff{ 315219820Sjeff DEBUG("linking: 0x%" PRIx64 " %p->%p:%u and 0x%" PRIx64 " %p->%p:%u", 316219820Sjeff node->nodeguid, node, port, port->portnum, 317219820Sjeff remotenode->nodeguid, remotenode, remoteport, remoteport->portnum); 318219820Sjeff if (port->remoteport) 319219820Sjeff port->remoteport->remoteport = NULL; 320219820Sjeff if (remoteport->remoteport) 321219820Sjeff remoteport->remoteport->remoteport = NULL; 322219820Sjeff port->remoteport = remoteport; 323219820Sjeff remoteport->remoteport = port; 324219820Sjeff} 325219820Sjeff 326219820Sjeffstatic int 327219820Sjeffhandle_port(Node *node, Port *port, ib_portid_t *path, int portnum, int dist) 328219820Sjeff{ 329219820Sjeff Node node_buf; 330219820Sjeff Port port_buf; 331219820Sjeff Node *remotenode, *oldnode; 332219820Sjeff Port *remoteport, *oldport; 333219820Sjeff 334219820Sjeff memset(&node_buf, 0, sizeof(node_buf)); 335219820Sjeff memset(&port_buf, 0, sizeof(port_buf)); 336219820Sjeff 337219820Sjeff DEBUG("handle node %p port %p:%d dist %d", node, port, portnum, dist); 338219820Sjeff if (port->physstate != 5) /* LinkUp */ 339219820Sjeff return -1; 340219820Sjeff 341219820Sjeff if (extend_dpath(&path->drpath, portnum) < 0) 342219820Sjeff return -1; 343219820Sjeff 344219820Sjeff if (get_node(&node_buf, &port_buf, path) < 0) { 345219820Sjeff IBWARN("NodeInfo on %s failed, skipping port", 346219820Sjeff portid2str(path)); 347219820Sjeff path->drpath.cnt--; /* restore path */ 348219820Sjeff return -1; 349219820Sjeff } 350219820Sjeff 351219820Sjeff oldnode = find_node(&node_buf); 352219820Sjeff if (oldnode) 353219820Sjeff remotenode = oldnode; 354219820Sjeff else if (!(remotenode = create_node(&node_buf, path, dist + 1))) 355219820Sjeff IBERROR("no memory"); 356219820Sjeff 357219820Sjeff oldport = find_port(remotenode, &port_buf); 358219820Sjeff if (oldport) { 359219820Sjeff remoteport = oldport; 360219820Sjeff if (node != remotenode || port != remoteport) 361219820Sjeff IBWARN("port moving..."); 362219820Sjeff } else if (!(remoteport = create_port(remotenode, &port_buf))) 363219820Sjeff IBERROR("no memory"); 364219820Sjeff 365219820Sjeff dump_endnode(path, oldnode ? "known remote" : "new remote", 366219820Sjeff remotenode, remoteport); 367219820Sjeff 368219820Sjeff link_ports(node, port, remotenode, remoteport); 369219820Sjeff 370219820Sjeff path->drpath.cnt--; /* restore path */ 371219820Sjeff return 0; 372219820Sjeff} 373219820Sjeff 374219820Sjeff/* 375219820Sjeff * Return 1 if found, 0 if not, -1 on errors. 376219820Sjeff */ 377219820Sjeffstatic int 378219820Sjeffdiscover(ib_portid_t *from) 379219820Sjeff{ 380219820Sjeff Node node_buf; 381219820Sjeff Port port_buf; 382219820Sjeff Node *node; 383219820Sjeff Port *port; 384219820Sjeff int i; 385219820Sjeff int dist = 0; 386219820Sjeff ib_portid_t *path; 387219820Sjeff 388219820Sjeff DEBUG("from %s", portid2str(from)); 389219820Sjeff 390219820Sjeff memset(&node_buf, 0, sizeof(node_buf)); 391219820Sjeff memset(&port_buf, 0, sizeof(port_buf)); 392219820Sjeff 393219820Sjeff if (get_node(&node_buf, &port_buf, from) < 0) { 394219820Sjeff IBWARN("can't reach node %s", portid2str(from)); 395219820Sjeff return -1; 396219820Sjeff } 397219820Sjeff 398219820Sjeff node = create_node(&node_buf, from, 0); 399219820Sjeff if (!node) 400219820Sjeff IBERROR("out of memory"); 401219820Sjeff 402219820Sjeff mynode = node; 403219820Sjeff 404219820Sjeff port = create_port(node, &port_buf); 405219820Sjeff if (!port) 406219820Sjeff IBERROR("out of memory"); 407219820Sjeff 408219820Sjeff if (node->type != SWITCH_NODE && 409219820Sjeff handle_port(node, port, from, node->localport, 0) < 0) 410219820Sjeff return 0; 411219820Sjeff 412219820Sjeff for (dist = 0; dist < MAXHOPS; dist++) { 413219820Sjeff 414219820Sjeff for (node = nodesdist[dist]; node; node = node->dnext) { 415219820Sjeff 416219820Sjeff path = &node->path; 417219820Sjeff 418219820Sjeff DEBUG("dist %d node %p", dist, node); 419219820Sjeff dump_endnode(path, "processing", node, port); 420219820Sjeff 421219820Sjeff for (i = 1; i <= node->numports; i++) { 422219820Sjeff if (i == node->localport) 423219820Sjeff continue; 424219820Sjeff 425219820Sjeff if (get_port(&port_buf, i, path) < 0) { 426219820Sjeff IBWARN("can't reach node %s port %d", portid2str(path), i); 427219820Sjeff continue; 428219820Sjeff } 429219820Sjeff 430219820Sjeff port = find_port(node, &port_buf); 431219820Sjeff if (port) 432219820Sjeff continue; 433219820Sjeff 434219820Sjeff port = create_port(node, &port_buf); 435219820Sjeff if (!port) 436219820Sjeff IBERROR("out of memory"); 437219820Sjeff 438219820Sjeff /* If switch, set port GUID to node GUID */ 439219820Sjeff if (node->type == SWITCH_NODE) 440219820Sjeff port->portguid = node->portguid; 441219820Sjeff 442219820Sjeff handle_port(node, port, path, i, dist); 443219820Sjeff } 444219820Sjeff } 445219820Sjeff } 446219820Sjeff 447219820Sjeff return 0; 448219820Sjeff} 449219820Sjeff 450219820Sjeffchar * 451219820Sjeffnode_name(Node *node) 452219820Sjeff{ 453219820Sjeff static char buf[256]; 454219820Sjeff 455219820Sjeff switch(node->type) { 456219820Sjeff case SWITCH_NODE: 457219820Sjeff sprintf(buf, "\"%s", "S"); 458219820Sjeff break; 459219820Sjeff case CA_NODE: 460219820Sjeff sprintf(buf, "\"%s", "H"); 461219820Sjeff break; 462219820Sjeff case ROUTER_NODE: 463219820Sjeff sprintf(buf, "\"%s", "R"); 464219820Sjeff break; 465219820Sjeff default: 466219820Sjeff sprintf(buf, "\"%s", "?"); 467219820Sjeff break; 468219820Sjeff } 469219820Sjeff sprintf(buf+2, "-%016" PRIx64 "\"", node->nodeguid); 470219820Sjeff 471219820Sjeff return buf; 472219820Sjeff} 473219820Sjeff 474219820Sjeffvoid 475219820Sjefflist_node(Node *node) 476219820Sjeff{ 477219820Sjeff char *node_type; 478219820Sjeff char *nodename = remap_node_name(node_name_map, node->nodeguid, 479219820Sjeff node->nodedesc); 480219820Sjeff 481219820Sjeff switch(node->type) { 482219820Sjeff case SWITCH_NODE: 483219820Sjeff node_type = "Switch"; 484219820Sjeff break; 485219820Sjeff case CA_NODE: 486219820Sjeff node_type = "Ca"; 487219820Sjeff break; 488219820Sjeff case ROUTER_NODE: 489219820Sjeff node_type = "Router"; 490219820Sjeff break; 491219820Sjeff default: 492219820Sjeff node_type = "???"; 493219820Sjeff break; 494219820Sjeff } 495219820Sjeff fprintf(f, "%s\t : 0x%016" PRIx64 " ports %d devid 0x%x vendid 0x%x \"%s\"\n", 496219820Sjeff node_type, 497219820Sjeff node->nodeguid, node->numports, node->devid, node->vendid, 498219820Sjeff nodename); 499219820Sjeff 500219820Sjeff free(nodename); 501219820Sjeff} 502219820Sjeff 503219820Sjeffvoid 504219820Sjeffout_ids(Node *node, int group, char *chname) 505219820Sjeff{ 506219820Sjeff fprintf(f, "\nvendid=0x%x\ndevid=0x%x\n", node->vendid, node->devid); 507219820Sjeff if (node->sysimgguid) 508219820Sjeff fprintf(f, "sysimgguid=0x%" PRIx64, node->sysimgguid); 509219820Sjeff if (group 510219820Sjeff && node->chrecord && node->chrecord->chassisnum) { 511219820Sjeff fprintf(f, "\t\t# Chassis %d", node->chrecord->chassisnum); 512219820Sjeff if (chname) 513219820Sjeff fprintf(f, " (%s)", chname); 514219820Sjeff if (is_xsigo_tca(node->nodeguid) && node->ports->remoteport) 515219820Sjeff fprintf(f, " slot %d", node->ports->remoteport->portnum); 516219820Sjeff } 517219820Sjeff fprintf(f, "\n"); 518219820Sjeff} 519219820Sjeff 520219820Sjeffuint64_t 521219820Sjeffout_chassis(int chassisnum) 522219820Sjeff{ 523219820Sjeff uint64_t guid; 524219820Sjeff 525219820Sjeff fprintf(f, "\nChassis %d", chassisnum); 526219820Sjeff guid = get_chassis_guid(chassisnum); 527219820Sjeff if (guid) 528219820Sjeff fprintf(f, " (guid 0x%" PRIx64 ")", guid); 529219820Sjeff fprintf(f, "\n"); 530219820Sjeff return guid; 531219820Sjeff} 532219820Sjeff 533219820Sjeffvoid 534219820Sjeffout_switch(Node *node, int group, char *chname) 535219820Sjeff{ 536219820Sjeff char *str; 537219820Sjeff char *nodename = NULL; 538219820Sjeff 539219820Sjeff out_ids(node, group, chname); 540219820Sjeff fprintf(f, "switchguid=0x%" PRIx64, node->nodeguid); 541219820Sjeff fprintf(f, "(%" PRIx64 ")", node->portguid); 542219820Sjeff /* Currently, only if Voltaire chassis */ 543219820Sjeff if (group 544219820Sjeff && node->chrecord && node->chrecord->chassisnum 545219820Sjeff && node->vendid == VTR_VENDOR_ID) { 546219820Sjeff str = get_chassis_type(node->chrecord->chassistype); 547219820Sjeff if (str) 548219820Sjeff fprintf(f, "%s ", str); 549219820Sjeff str = get_chassis_slot(node->chrecord->chassisslot); 550219820Sjeff if (str) 551219820Sjeff fprintf(f, "%s ", str); 552219820Sjeff fprintf(f, "%d Chip %d", node->chrecord->slotnum, node->chrecord->anafanum); 553219820Sjeff } 554219820Sjeff 555219820Sjeff nodename = remap_node_name(node_name_map, node->nodeguid, 556219820Sjeff node->nodedesc); 557219820Sjeff 558219820Sjeff fprintf(f, "\nSwitch\t%d %s\t\t# \"%s\" %s port 0 lid %d lmc %d\n", 559219820Sjeff node->numports, node_name(node), 560219820Sjeff nodename, 561219820Sjeff node->smaenhsp0 ? "enhanced" : "base", 562219820Sjeff node->smalid, node->smalmc); 563219820Sjeff 564219820Sjeff free(nodename); 565219820Sjeff} 566219820Sjeff 567219820Sjeffvoid 568219820Sjeffout_ca(Node *node, int group, char *chname) 569219820Sjeff{ 570219820Sjeff char *node_type; 571219820Sjeff char *node_type2; 572219820Sjeff char *nodename = remap_node_name(node_name_map, node->nodeguid, 573219820Sjeff node->nodedesc); 574219820Sjeff 575219820Sjeff out_ids(node, group, chname); 576219820Sjeff switch(node->type) { 577219820Sjeff case CA_NODE: 578219820Sjeff node_type = "ca"; 579219820Sjeff node_type2 = "Ca"; 580219820Sjeff break; 581219820Sjeff case ROUTER_NODE: 582219820Sjeff node_type = "rt"; 583219820Sjeff node_type2 = "Rt"; 584219820Sjeff break; 585219820Sjeff default: 586219820Sjeff node_type = "???"; 587219820Sjeff node_type2 = "???"; 588219820Sjeff break; 589219820Sjeff } 590219820Sjeff 591219820Sjeff fprintf(f, "%sguid=0x%" PRIx64 "\n", node_type, node->nodeguid); 592219820Sjeff fprintf(f, "%s\t%d %s\t\t# \"%s\"", 593219820Sjeff node_type2, node->numports, node_name(node), 594219820Sjeff nodename); 595219820Sjeff if (group && is_xsigo_hca(node->nodeguid)) 596219820Sjeff fprintf(f, " (scp)"); 597219820Sjeff fprintf(f, "\n"); 598219820Sjeff 599219820Sjeff free(nodename); 600219820Sjeff} 601219820Sjeff 602219820Sjeffstatic char * 603219820Sjeffout_ext_port(Port *port, int group) 604219820Sjeff{ 605219820Sjeff char *str = NULL; 606219820Sjeff 607219820Sjeff /* Currently, only if Voltaire chassis */ 608219820Sjeff if (group 609219820Sjeff && port->node->chrecord && port->node->vendid == VTR_VENDOR_ID) 610219820Sjeff str = portmapstring(port); 611219820Sjeff 612219820Sjeff return (str); 613219820Sjeff} 614219820Sjeff 615219820Sjeffvoid 616219820Sjeffout_switch_port(Port *port, int group) 617219820Sjeff{ 618219820Sjeff char *ext_port_str = NULL; 619219820Sjeff char *rem_nodename = NULL; 620219820Sjeff 621219820Sjeff DEBUG("port %p:%d remoteport %p", port, port->portnum, port->remoteport); 622219820Sjeff fprintf(f, "[%d]", port->portnum); 623219820Sjeff 624219820Sjeff ext_port_str = out_ext_port(port, group); 625219820Sjeff if (ext_port_str) 626219820Sjeff fprintf(f, "%s", ext_port_str); 627219820Sjeff 628219820Sjeff rem_nodename = remap_node_name(node_name_map, 629219820Sjeff port->remoteport->node->nodeguid, 630219820Sjeff port->remoteport->node->nodedesc); 631219820Sjeff 632219820Sjeff ext_port_str = out_ext_port(port->remoteport, group); 633219820Sjeff fprintf(f, "\t%s[%d]%s", 634219820Sjeff node_name(port->remoteport->node), 635219820Sjeff port->remoteport->portnum, 636219820Sjeff ext_port_str ? ext_port_str : ""); 637219820Sjeff if (port->remoteport->node->type != SWITCH_NODE) 638219820Sjeff fprintf(f, "(%" PRIx64 ") ", port->remoteport->portguid); 639219820Sjeff fprintf(f, "\t\t# \"%s\" lid %d %s%s", 640219820Sjeff rem_nodename, 641219820Sjeff port->remoteport->node->type == SWITCH_NODE ? port->remoteport->node->smalid : port->remoteport->lid, 642219820Sjeff get_linkwidth_str(port->linkwidth), 643219820Sjeff get_linkspeed_str(port->linkspeed)); 644219820Sjeff 645219820Sjeff if (is_xsigo_tca(port->remoteport->portguid)) 646219820Sjeff fprintf(f, " slot %d", port->portnum); 647219820Sjeff else if (is_xsigo_hca(port->remoteport->portguid)) 648219820Sjeff fprintf(f, " (scp)"); 649219820Sjeff fprintf(f, "\n"); 650219820Sjeff 651219820Sjeff free(rem_nodename); 652219820Sjeff} 653219820Sjeff 654219820Sjeffvoid 655219820Sjeffout_ca_port(Port *port, int group) 656219820Sjeff{ 657219820Sjeff char *str = NULL; 658219820Sjeff char *rem_nodename = NULL; 659219820Sjeff 660219820Sjeff fprintf(f, "[%d]", port->portnum); 661219820Sjeff if (port->node->type != SWITCH_NODE) 662219820Sjeff fprintf(f, "(%" PRIx64 ") ", port->portguid); 663219820Sjeff fprintf(f, "\t%s[%d]", 664219820Sjeff node_name(port->remoteport->node), 665219820Sjeff port->remoteport->portnum); 666219820Sjeff str = out_ext_port(port->remoteport, group); 667219820Sjeff if (str) 668219820Sjeff fprintf(f, "%s", str); 669219820Sjeff if (port->remoteport->node->type != SWITCH_NODE) 670219820Sjeff fprintf(f, " (%" PRIx64 ") ", port->remoteport->portguid); 671219820Sjeff 672219820Sjeff rem_nodename = remap_node_name(node_name_map, 673219820Sjeff port->remoteport->node->nodeguid, 674219820Sjeff port->remoteport->node->nodedesc); 675219820Sjeff 676219820Sjeff fprintf(f, "\t\t# lid %d lmc %d \"%s\" lid %d %s%s\n", 677219820Sjeff port->lid, port->lmc, rem_nodename, 678219820Sjeff port->remoteport->node->type == SWITCH_NODE ? port->remoteport->node->smalid : port->remoteport->lid, 679219820Sjeff get_linkwidth_str(port->linkwidth), 680219820Sjeff get_linkspeed_str(port->linkspeed)); 681219820Sjeff 682219820Sjeff free(rem_nodename); 683219820Sjeff} 684219820Sjeff 685219820Sjeffint 686219820Sjeffdump_topology(int listtype, int group) 687219820Sjeff{ 688219820Sjeff Node *node; 689219820Sjeff Port *port; 690219820Sjeff int i = 0, dist = 0; 691219820Sjeff time_t t = time(0); 692219820Sjeff uint64_t chguid; 693219820Sjeff char *chname = NULL; 694219820Sjeff 695219820Sjeff if (!listtype) { 696219820Sjeff fprintf(f, "#\n# Topology file: generated on %s#\n", ctime(&t)); 697219820Sjeff fprintf(f, "# Max of %d hops discovered\n", maxhops_discovered); 698219820Sjeff fprintf(f, "# Initiated from node %016" PRIx64 " port %016" PRIx64 "\n", mynode->nodeguid, mynode->portguid); 699219820Sjeff } 700219820Sjeff 701219820Sjeff /* Make pass on switches */ 702219820Sjeff if (group && !listtype) { 703219820Sjeff ChassisList *ch = NULL; 704219820Sjeff 705219820Sjeff /* Chassis based switches first */ 706219820Sjeff for (ch = chassis; ch; ch = ch->next) { 707219820Sjeff int n = 0; 708219820Sjeff 709219820Sjeff if (!ch->chassisnum) 710219820Sjeff continue; 711219820Sjeff chguid = out_chassis(ch->chassisnum); 712219820Sjeff if (chname) 713219820Sjeff free(chname); 714219820Sjeff chname = NULL; 715219820Sjeff if (is_xsigo_guid(chguid)) { 716219820Sjeff for (node = nodesdist[MAXHOPS]; node; node = node->dnext) { 717219820Sjeff if (!node->chrecord || 718219820Sjeff !node->chrecord->chassisnum) 719219820Sjeff continue; 720219820Sjeff 721219820Sjeff if (node->chrecord->chassisnum != ch->chassisnum) 722219820Sjeff continue; 723219820Sjeff 724219820Sjeff if (is_xsigo_hca(node->nodeguid)) { 725219820Sjeff chname = remap_node_name(node_name_map, 726219820Sjeff node->nodeguid, 727219820Sjeff node->nodedesc); 728219820Sjeff fprintf(f, "Hostname: %s\n", chname); 729219820Sjeff } 730219820Sjeff } 731219820Sjeff } 732219820Sjeff 733219820Sjeff fprintf(f, "\n# Spine Nodes"); 734219820Sjeff for (n = 1; n <= (SPINES_MAX_NUM+1); n++) { 735219820Sjeff if (ch->spinenode[n]) { 736219820Sjeff out_switch(ch->spinenode[n], group, chname); 737219820Sjeff for (port = ch->spinenode[n]->ports; port; port = port->next, i++) 738219820Sjeff if (port->remoteport) 739219820Sjeff out_switch_port(port, group); 740219820Sjeff } 741219820Sjeff } 742219820Sjeff fprintf(f, "\n# Line Nodes"); 743219820Sjeff for (n = 1; n <= (LINES_MAX_NUM+1); n++) { 744219820Sjeff if (ch->linenode[n]) { 745219820Sjeff out_switch(ch->linenode[n], group, chname); 746219820Sjeff for (port = ch->linenode[n]->ports; port; port = port->next, i++) 747219820Sjeff if (port->remoteport) 748219820Sjeff out_switch_port(port, group); 749219820Sjeff } 750219820Sjeff } 751219820Sjeff 752219820Sjeff fprintf(f, "\n# Chassis Switches"); 753219820Sjeff for (dist = 0; dist <= maxhops_discovered; dist++) { 754219820Sjeff 755219820Sjeff for (node = nodesdist[dist]; node; node = node->dnext) { 756219820Sjeff 757219820Sjeff /* Non Voltaire chassis */ 758219820Sjeff if (node->vendid == VTR_VENDOR_ID) 759219820Sjeff continue; 760219820Sjeff if (!node->chrecord || 761219820Sjeff !node->chrecord->chassisnum) 762219820Sjeff continue; 763219820Sjeff 764219820Sjeff if (node->chrecord->chassisnum != ch->chassisnum) 765219820Sjeff continue; 766219820Sjeff 767219820Sjeff out_switch(node, group, chname); 768219820Sjeff for (port = node->ports; port; port = port->next, i++) 769219820Sjeff if (port->remoteport) 770219820Sjeff out_switch_port(port, group); 771219820Sjeff 772219820Sjeff } 773219820Sjeff 774219820Sjeff } 775219820Sjeff 776219820Sjeff fprintf(f, "\n# Chassis CAs"); 777219820Sjeff for (node = nodesdist[MAXHOPS]; node; node = node->dnext) { 778219820Sjeff if (!node->chrecord || 779219820Sjeff !node->chrecord->chassisnum) 780219820Sjeff continue; 781219820Sjeff 782219820Sjeff if (node->chrecord->chassisnum != ch->chassisnum) 783219820Sjeff continue; 784219820Sjeff 785219820Sjeff out_ca(node, group, chname); 786219820Sjeff for (port = node->ports; port; port = port->next, i++) 787219820Sjeff if (port->remoteport) 788219820Sjeff out_ca_port(port, group); 789219820Sjeff 790219820Sjeff } 791219820Sjeff 792219820Sjeff } 793219820Sjeff 794219820Sjeff } else { 795219820Sjeff for (dist = 0; dist <= maxhops_discovered; dist++) { 796219820Sjeff 797219820Sjeff for (node = nodesdist[dist]; node; node = node->dnext) { 798219820Sjeff 799219820Sjeff DEBUG("SWITCH: dist %d node %p", dist, node); 800219820Sjeff if (!listtype) 801219820Sjeff out_switch(node, group, chname); 802219820Sjeff else { 803219820Sjeff if (listtype & LIST_SWITCH_NODE) 804219820Sjeff list_node(node); 805219820Sjeff continue; 806219820Sjeff } 807219820Sjeff 808219820Sjeff for (port = node->ports; port; port = port->next, i++) 809219820Sjeff if (port->remoteport) 810219820Sjeff out_switch_port(port, group); 811219820Sjeff } 812219820Sjeff } 813219820Sjeff } 814219820Sjeff 815219820Sjeff if (chname) 816219820Sjeff free(chname); 817219820Sjeff chname = NULL; 818219820Sjeff if (group && !listtype) { 819219820Sjeff 820219820Sjeff fprintf(f, "\nNon-Chassis Nodes\n"); 821219820Sjeff 822219820Sjeff for (dist = 0; dist <= maxhops_discovered; dist++) { 823219820Sjeff 824219820Sjeff for (node = nodesdist[dist]; node; node = node->dnext) { 825219820Sjeff 826219820Sjeff DEBUG("SWITCH: dist %d node %p", dist, node); 827219820Sjeff /* Now, skip chassis based switches */ 828219820Sjeff if (node->chrecord && 829219820Sjeff node->chrecord->chassisnum) 830219820Sjeff continue; 831219820Sjeff out_switch(node, group, chname); 832219820Sjeff 833219820Sjeff for (port = node->ports; port; port = port->next, i++) 834219820Sjeff if (port->remoteport) 835219820Sjeff out_switch_port(port, group); 836219820Sjeff } 837219820Sjeff 838219820Sjeff } 839219820Sjeff 840219820Sjeff } 841219820Sjeff 842219820Sjeff /* Make pass on CAs */ 843219820Sjeff for (node = nodesdist[MAXHOPS]; node; node = node->dnext) { 844219820Sjeff 845219820Sjeff DEBUG("CA: dist %d node %p", dist, node); 846219820Sjeff if (!listtype) { 847219820Sjeff /* Now, skip chassis based CAs */ 848219820Sjeff if (group && node->chrecord && 849219820Sjeff node->chrecord->chassisnum) 850219820Sjeff continue; 851219820Sjeff out_ca(node, group, chname); 852219820Sjeff } else { 853219820Sjeff if (((listtype & LIST_CA_NODE) && (node->type == CA_NODE)) || 854219820Sjeff ((listtype & LIST_ROUTER_NODE) && (node->type == ROUTER_NODE))) 855219820Sjeff list_node(node); 856219820Sjeff continue; 857219820Sjeff } 858219820Sjeff 859219820Sjeff for (port = node->ports; port; port = port->next, i++) 860219820Sjeff if (port->remoteport) 861219820Sjeff out_ca_port(port, group); 862219820Sjeff } 863219820Sjeff 864219820Sjeff if (chname) 865219820Sjeff free(chname); 866219820Sjeff 867219820Sjeff return i; 868219820Sjeff} 869219820Sjeff 870219820Sjeffvoid dump_ports_report () 871219820Sjeff{ 872219820Sjeff int b, n = 0, p; 873219820Sjeff Node *node; 874219820Sjeff Port *port; 875219820Sjeff 876219820Sjeff // If switch and LID == 0, search of other switch ports with 877219820Sjeff // valid LID and assign it to all ports of that switch 878219820Sjeff for (b = 0; b <= MAXHOPS; b++) 879219820Sjeff for (node = nodesdist[b]; node; node = node->dnext) 880219820Sjeff if (node->type == SWITCH_NODE) { 881219820Sjeff int swlid = 0; 882219820Sjeff for (p = 0, port = node->ports; 883219820Sjeff p < node->numports && port && !swlid; 884219820Sjeff port = port->next) 885219820Sjeff if (port->lid != 0) 886219820Sjeff swlid = port->lid; 887219820Sjeff for (p = 0, port = node->ports; 888219820Sjeff p < node->numports && port; 889219820Sjeff port = port->next) 890219820Sjeff port->lid = swlid; 891219820Sjeff } 892219820Sjeff 893219820Sjeff for (b = 0; b <= MAXHOPS; b++) 894219820Sjeff for (node = nodesdist[b]; node; node = node->dnext) { 895219820Sjeff for (p = 0, port = node->ports; 896219820Sjeff p < node->numports && port; 897219820Sjeff p++, port = port->next) { 898219820Sjeff fprintf(stdout, 899219820Sjeff "%2s %5d %2d 0x%016" PRIx64 " %s %s", 900219820Sjeff node_type_str2(port->node), port->lid, 901219820Sjeff port->portnum, 902219820Sjeff port->portguid, 903219820Sjeff get_linkwidth_str(port->linkwidth), 904219820Sjeff get_linkspeed_str(port->linkspeed)); 905219820Sjeff if (port->remoteport) 906219820Sjeff fprintf(stdout, 907219820Sjeff " - %2s %5d %2d 0x%016" PRIx64 908219820Sjeff " ( '%s' - '%s' )\n", 909219820Sjeff node_type_str2(port->remoteport->node), 910219820Sjeff port->remoteport->lid, 911219820Sjeff port->remoteport->portnum, 912219820Sjeff port->remoteport->portguid, 913219820Sjeff port->node->nodedesc, 914219820Sjeff port->remoteport->node->nodedesc); 915219820Sjeff else 916219820Sjeff fprintf(stdout, "%36s'%s'\n", "", 917219820Sjeff port->node->nodedesc); 918219820Sjeff } 919219820Sjeff n++; 920219820Sjeff } 921219820Sjeff} 922219820Sjeff 923219820Sjeffvoid 924219820Sjeffusage(void) 925219820Sjeff{ 926219820Sjeff 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 " 927219820Sjeff "-t(imeout) timeout_ms --node-name-map node-name-map] -p(orts) [<topology-file>]\n", 928219820Sjeff argv0); 929219820Sjeff fprintf(stderr, " --node-name-map <node-name-map> specify a node name map file\n"); 930219820Sjeff exit(-1); 931219820Sjeff} 932219820Sjeff 933219820Sjeffint 934219820Sjeffmain(int argc, char **argv) 935219820Sjeff{ 936219820Sjeff int mgmt_classes[2] = {IB_SMI_CLASS, IB_SMI_DIRECT_CLASS}; 937219820Sjeff ib_portid_t my_portid = {0}; 938219820Sjeff int udebug = 0, list = 0; 939219820Sjeff char *ca = 0; 940219820Sjeff int ca_port = 0; 941219820Sjeff int group = 0; 942219820Sjeff int ports_report = 0; 943219820Sjeff 944219820Sjeff static char const str_opts[] = "C:P:t:devslgHSRpVhu"; 945219820Sjeff static const struct option long_opts[] = { 946219820Sjeff { "C", 1, 0, 'C'}, 947219820Sjeff { "P", 1, 0, 'P'}, 948219820Sjeff { "debug", 0, 0, 'd'}, 949219820Sjeff { "err_show", 0, 0, 'e'}, 950219820Sjeff { "verbose", 0, 0, 'v'}, 951219820Sjeff { "show", 0, 0, 's'}, 952219820Sjeff { "list", 0, 0, 'l'}, 953219820Sjeff { "grouping", 0, 0, 'g'}, 954219820Sjeff { "Hca_list", 0, 0, 'H'}, 955219820Sjeff { "Switch_list", 0, 0, 'S'}, 956219820Sjeff { "Router_list", 0, 0, 'R'}, 957219820Sjeff { "timeout", 1, 0, 't'}, 958219820Sjeff { "node-name-map", 1, 0, 1}, 959219820Sjeff { "ports", 0, 0, 'p'}, 960219820Sjeff { "Version", 0, 0, 'V'}, 961219820Sjeff { "help", 0, 0, 'h'}, 962219820Sjeff { "usage", 0, 0, 'u'}, 963219820Sjeff { } 964219820Sjeff }; 965219820Sjeff 966219820Sjeff f = stdout; 967219820Sjeff 968219820Sjeff argv0 = argv[0]; 969219820Sjeff 970219820Sjeff while (1) { 971219820Sjeff int ch = getopt_long(argc, argv, str_opts, long_opts, NULL); 972219820Sjeff if ( ch == -1 ) 973219820Sjeff break; 974219820Sjeff switch(ch) { 975219820Sjeff case 1: 976219820Sjeff node_name_map_file = strdup(optarg); 977219820Sjeff break; 978219820Sjeff case 'C': 979219820Sjeff ca = optarg; 980219820Sjeff break; 981219820Sjeff case 'P': 982219820Sjeff ca_port = strtoul(optarg, 0, 0); 983219820Sjeff break; 984219820Sjeff case 'd': 985219820Sjeff ibdebug++; 986219820Sjeff madrpc_show_errors(1); 987219820Sjeff umad_debug(udebug); 988219820Sjeff udebug++; 989219820Sjeff break; 990219820Sjeff case 't': 991219820Sjeff timeout = strtoul(optarg, 0, 0); 992219820Sjeff break; 993219820Sjeff case 'v': 994219820Sjeff verbose++; 995219820Sjeff dumplevel++; 996219820Sjeff break; 997219820Sjeff case 's': 998219820Sjeff dumplevel = 1; 999219820Sjeff break; 1000219820Sjeff case 'e': 1001219820Sjeff madrpc_show_errors(1); 1002219820Sjeff break; 1003219820Sjeff case 'l': 1004219820Sjeff list = LIST_CA_NODE | LIST_SWITCH_NODE | LIST_ROUTER_NODE; 1005219820Sjeff break; 1006219820Sjeff case 'g': 1007219820Sjeff group = 1; 1008219820Sjeff break; 1009219820Sjeff case 'S': 1010219820Sjeff list = LIST_SWITCH_NODE; 1011219820Sjeff break; 1012219820Sjeff case 'H': 1013219820Sjeff list = LIST_CA_NODE; 1014219820Sjeff break; 1015219820Sjeff case 'R': 1016219820Sjeff list = LIST_ROUTER_NODE; 1017219820Sjeff break; 1018219820Sjeff case 'V': 1019219820Sjeff fprintf(stderr, "%s %s\n", argv0, get_build_version() ); 1020219820Sjeff exit(-1); 1021219820Sjeff case 'p': 1022219820Sjeff ports_report = 1; 1023219820Sjeff break; 1024219820Sjeff default: 1025219820Sjeff usage(); 1026219820Sjeff break; 1027219820Sjeff } 1028219820Sjeff } 1029219820Sjeff argc -= optind; 1030219820Sjeff argv += optind; 1031219820Sjeff 1032219820Sjeff if (argc && !(f = fopen(argv[0], "w"))) 1033219820Sjeff IBERROR("can't open file %s for writing", argv[0]); 1034219820Sjeff 1035219820Sjeff madrpc_init(ca, ca_port, mgmt_classes, 2); 1036219820Sjeff node_name_map = open_node_name_map(node_name_map_file); 1037219820Sjeff 1038219820Sjeff if (discover(&my_portid) < 0) 1039219820Sjeff IBERROR("discover"); 1040219820Sjeff 1041219820Sjeff if (group) 1042219820Sjeff chassis = group_nodes(); 1043219820Sjeff 1044219820Sjeff if (ports_report) 1045219820Sjeff dump_ports_report(); 1046219820Sjeff else 1047219820Sjeff dump_topology(list, group); 1048219820Sjeff 1049219820Sjeff close_node_name_map(node_name_map); 1050219820Sjeff exit(0); 1051219820Sjeff} 1052