void out_ids(ibnd_node_t * node, int group, char *chname, char *out_prefix) { uint64_t sysimgguid = mad_get_field64(node->info, 0, IB_NODE_SYSTEM_GUID_F); fprintf(f, "\n%svendid=0x%x\n", out_prefix ? out_prefix : "", mad_get_field(node->info, 0, IB_NODE_VENDORID_F)); fprintf(f, "%sdevid=0x%x\n", out_prefix ? out_prefix : "", mad_get_field(node->info, 0, IB_NODE_DEVID_F)); if (sysimgguid) fprintf(f, "%ssysimgguid=0x%" PRIx64, out_prefix ? out_prefix : "", sysimgguid); if (group && node->chassis && node->chassis->chassisnum) { fprintf(f, "\t\t# Chassis %d", node->chassis->chassisnum); if (chname) fprintf(f, " (%s)", clean_nodedesc(chname)); if (ibnd_is_xsigo_tca(node->guid) && node->ports[1] && node->ports[1]->remoteport) fprintf(f, " slot %d", node->ports[1]->remoteport->portnum); } if (sysimgguid || (group && node->chassis && node->chassis->chassisnum)) fprintf(f, "\n"); }
char * dump_unicast_tables(ib_portid_t *portid, int startlid, int endlid) { char lft[IB_SMP_DATA_SIZE]; char nd[IB_SMP_DATA_SIZE]; uint8_t sw[IB_SMP_DATA_SIZE]; char str[200], *s; uint64_t nodeguid; int block, i, e, nports, top; int n = 0, startblock, endblock; if ((s = check_switch(portid, &nports, &nodeguid, sw, nd))) return s; mad_decode_field(sw, IB_SW_LINEAR_FDB_TOP_F, &top); if (!endlid || endlid > top) endlid = top; if (endlid > IB_MAX_UCAST_LID) { IBWARN("ilegal lft top %d, truncate to %d", endlid, IB_MAX_UCAST_LID); endlid = IB_MAX_UCAST_LID; } printf("Unicast lids [0x%x-0x%x] of switch %s guid 0x%016" PRIx64 " (%s):\n", startlid, endlid, portid2str(portid), nodeguid, clean_nodedesc(nd)); DEBUG("Switch top is 0x%x\n", top); printf(" Lid Out Destination\n"); printf(" Port Info \n"); startblock = startlid / IB_SMP_DATA_SIZE; endblock = ALIGN(endlid, IB_SMP_DATA_SIZE) / IB_SMP_DATA_SIZE; for (block = startblock; block <= endblock; block++) { DEBUG("reading block %d", block); if (!smp_query(lft, portid, IB_ATTR_LINEARFORWTBL, block, 0)) return "linear forwarding table get failed"; i = block * IB_SMP_DATA_SIZE; e = i + IB_SMP_DATA_SIZE; if (i < startlid) i = startlid; if (e > endlid + 1) e = endlid + 1; for (;i < e; i++) { unsigned outport = lft[i % IB_SMP_DATA_SIZE]; unsigned valid = (outport <= nports); if (!valid && !dump_all) continue; dump_lid(str, sizeof str, i, valid); printf("0x%04x %03u %s\n", i, outport & 0xff, str); n++; } } printf("%d %slids dumped \n", n, dump_all ? "" : "valid "); return 0; }
static void dump_endnode(ib_portid_t *path, char *prompt, Node *node, Port *port) { if (!dumplevel) return; fprintf(f, "%s -> %s %s {%016" PRIx64 "} portnum %d lid %d-%d\"%s\"\n", portid2str(path), prompt, (node->type <= IB_NODE_MAX ? node_type_str[node->type] : "???"), node->nodeguid, node->type == SWITCH_NODE ? 0 : port->portnum, port->lid, port->lid + (1 << port->lmc) - 1, clean_nodedesc(node->nodedesc)); }
char *remap_node_name(nn_map_t * map, uint64_t target_guid, char *nodedesc) { char *rc = NULL; name_map_item_t *item = NULL; if (!map) goto done; item = (name_map_item_t *) cl_qmap_get(map, target_guid); if (item != (name_map_item_t *) cl_qmap_end(map)) rc = strdup(item->name); done: if (rc == NULL) rc = strdup(clean_nodedesc(nodedesc)); return (rc); }
void out_ca_detail(ibnd_node_t * node, char *ca_prefix) { char *node_type; switch (node->type) { case IB_NODE_CA: node_type = "Ca"; break; case IB_NODE_ROUTER: node_type = "Rt"; break; default: node_type = "???"; break; } fprintf(f, "%s%s\t%d %s\t\t# \"%s\"", ca_prefix ? ca_prefix : "", node_type, node->numports, node_name(node), clean_nodedesc(node->nodedesc)); }
int dump_lid(char *str, int strlen, int lid, int valid) { char nd[IB_SMP_DATA_SIZE] = {0}; uint8_t ni[IB_SMP_DATA_SIZE] = {0}; uint8_t pi[IB_SMP_DATA_SIZE] = {0}; ib_portid_t lidport = {0}; static int last_port_lid, base_port_lid; char ntype[50], sguid[30], desc[64]; static uint64_t portguid; int baselid, lmc, type; if (brief) { str[0] = 0; return 0; } if (lid <= last_port_lid) { if (!valid) return snprintf(str, strlen, ": (path #%d - illegal port)", lid - base_port_lid); else if (!portguid) return snprintf(str, strlen, ": (path #%d out of %d)", lid - base_port_lid + 1, last_port_lid - base_port_lid + 1); else { return snprintf(str, strlen, ": (path #%d out of %d: portguid %s)", lid - base_port_lid + 1, last_port_lid - base_port_lid + 1, mad_dump_val(IB_NODE_PORT_GUID_F, sguid, sizeof sguid, &portguid)); } } if (!valid) return snprintf(str, strlen, ": (illegal port)"); portguid = 0; lidport.lid = lid; if (!smp_query(nd, &lidport, IB_ATTR_NODE_DESC, 0, 100) || !smp_query(pi, &lidport, IB_ATTR_PORT_INFO, 0, 100) || !smp_query(ni, &lidport, IB_ATTR_NODE_INFO, 0, 100)) return snprintf(str, strlen, ": (unknown node and type)"); mad_decode_field(ni, IB_NODE_PORT_GUID_F, &portguid); mad_decode_field(ni, IB_NODE_TYPE_F, &type); mad_decode_field(pi, IB_PORT_LID_F, &baselid); mad_decode_field(pi, IB_PORT_LMC_F, &lmc); if (lmc > 0) { base_port_lid = baselid; last_port_lid = baselid + (1 << lmc) - 1; } return snprintf(str, strlen, ": (%s portguid %s: %s)", mad_dump_val(IB_NODE_TYPE_F, ntype, sizeof ntype, &type), mad_dump_val(IB_NODE_PORT_GUID_F, sguid, sizeof sguid, &portguid), mad_dump_val(IB_NODE_DESC_F, desc, sizeof desc, clean_nodedesc(nd))); }
char * dump_multicast_tables(ib_portid_t *portid, int startlid, int endlid) { char nd[IB_SMP_DATA_SIZE] = {0}; uint8_t sw[IB_SMP_DATA_SIZE] = {0}; char str[512]; char *s; uint64_t nodeguid; uint32_t mod; int block, i, j, e, nports, cap, chunks; int n = 0, startblock, lastblock; if ((s = check_switch(portid, &nports, &nodeguid, sw, nd))) return s; mad_decode_field(sw, IB_SW_MCAST_FDB_CAP_F, &cap); if (!endlid || endlid > IB_MIN_MCAST_LID + cap - 1) endlid = IB_MIN_MCAST_LID + cap - 1; if (!startlid) startlid = IB_MIN_MCAST_LID; if (startlid < IB_MIN_MCAST_LID) { IBWARN("illegal start mlid %x, set to %x", startlid, IB_MIN_MCAST_LID); startlid = IB_MIN_MCAST_LID; } if (endlid > IB_MAX_MCAST_LID) { IBWARN("illegal end mlid %x, truncate to %x", endlid, IB_MAX_MCAST_LID); endlid = IB_MAX_MCAST_LID; } printf("Multicast mlids [0x%x-0x%x] of switch %s guid 0x%016" PRIx64 " (%s):\n", startlid, endlid, portid2str(portid), nodeguid, clean_nodedesc(nd)); if (brief) printf(" MLid Port Mask\n"); else { if (nports > 9) { for (i = 0, s = str; i <= nports; i++) { *s++ = (i%10) ? ' ' : '0' + i/10; *s++ = ' '; } *s = 0; printf(" %s\n", str); } for (i = 0, s = str; i <= nports; i++) s += sprintf(s, "%d ", i%10); printf(" Ports: %s\n", str); printf(" MLid\n"); } if (verbose) printf("Switch muticast mlids capability is 0x%d\n", cap); chunks = ALIGN(nports + 1, 16) / 16; startblock = startlid / IB_MLIDS_IN_BLOCK; lastblock = endlid / IB_MLIDS_IN_BLOCK; for (block = startblock; block <= lastblock; block++) { for (j = 0; j < chunks; j++) { mod = (block - IB_MIN_MCAST_LID/IB_MLIDS_IN_BLOCK) | (j << 28); DEBUG("reading block %x chunk %d mod %x", block, j, mod); if (!smp_query(mft + j, portid, IB_ATTR_MULTICASTFORWTBL, mod, 0)) return "multicast forwarding table get failed"; } i = block * IB_MLIDS_IN_BLOCK; e = i + IB_MLIDS_IN_BLOCK; if (i < startlid) i = startlid; if (e > endlid + 1) e = endlid + 1; for (; i < e; i++) { if (dump_mlid(str, sizeof str, i, nports, mft) == 0) continue; printf("0x%04x %s\n", i, str); n++; } } printf("%d %smlids dumped \n", n, dump_all ? "" : "valid "); return 0; }
static int find_route(ib_portid_t * from, ib_portid_t * to, int dump) { Node *node, fromnode, tonode, nextnode; Port *port, fromport, toport, nextport; Switch sw; int maxhops = MAXHOPS; int portnum, outport; DEBUG("from %s", portid2str(from)); if (get_node(&fromnode, &fromport, from) < 0 || get_node(&tonode, &toport, to) < 0) { IBWARN("can't reach to/from ports"); if (!force) return -1; if (to->lid > 0) toport.lid = to->lid; IBWARN("Force: look for lid %d", to->lid); } node = &fromnode; port = &fromport; portnum = port->portnum; dump_endnode(dump, "From", node, port); while (maxhops--) { if (port->state != 4) goto badport; if (sameport(port, &toport)) break; /* found */ outport = portnum; if (node->type == IB_NODE_SWITCH) { DEBUG("switch node"); if ((outport = switch_lookup(&sw, from, to->lid)) < 0 || outport > node->numports) goto badtbl; if (extend_dpath(&from->drpath, outport) < 0) goto badpath; if (get_node(&nextnode, &nextport, from) < 0) { IBWARN("can't reach port at %s", portid2str(from)); return -1; } if (outport == 0) { if (!sameport(&nextport, &toport)) goto badtbl; else break; /* found SMA port */ } } else if ((node->type == IB_NODE_CA) || (node->type == IB_NODE_ROUTER)) { int ca_src = 0; DEBUG("ca or router node"); if (!sameport(port, &fromport)) { IBWARN ("can't continue: reached CA or router port %" PRIx64 ", lid %d", port->portguid, port->lid); return -1; } /* we are at CA or router "from" - go one hop back to (hopefully) a switch */ if (from->drpath.cnt > 0) { DEBUG("ca or router node - return back 1 hop"); from->drpath.cnt--; } else { ca_src = 1; if (portnum && extend_dpath(&from->drpath, portnum) < 0) goto badpath; } if (get_node(&nextnode, &nextport, from) < 0) { IBWARN("can't reach port at %s", portid2str(from)); return -1; } /* fix port num to be seen from the CA or router side */ if (!ca_src) nextport.portnum = from->drpath.p[from->drpath.cnt + 1]; } port = &nextport; if (port->state != 4) goto badoutport; node = &nextnode; portnum = port->portnum; dump_route(dump, node, outport, port); } if (maxhops <= 0) { IBWARN("no route found after %d hops", MAXHOPS); return -1; } dump_endnode(dump, "To", node, port); return 0; badport: IBWARN("Bad port state found: node \"%s\" port %d state %d", clean_nodedesc(node->nodedesc), portnum, port->state); return -1; badoutport: IBWARN("Bad out port state found: node \"%s\" outport %d state %d", clean_nodedesc(node->nodedesc), outport, port->state); return -1; badtbl: IBWARN ("Bad forwarding table entry found at: node \"%s\" lid entry %d is %d (top %d)", clean_nodedesc(node->nodedesc), to->lid, outport, sw.linearFDBtop); return -1; badpath: IBWARN("Direct path too long!"); return -1; }
int dump_topology(int group, ibnd_fabric_t * fabric) { ibnd_node_t *node; ibnd_port_t *port; int i = 0, p = 0; time_t t = time(0); uint64_t chguid; char *chname = NULL; struct iter_user_data iter_user_data; fprintf(f, "#\n# Topology file: generated on %s#\n", ctime(&t)); if (report_max_hops) fprintf(f, "# Reported max hops discovered: %u\n" "# Total MADs used: %u\n", fabric->maxhops_discovered, fabric->total_mads_used); fprintf(f, "# Initiated from node %016" PRIx64 " port %016" PRIx64 "\n", fabric->from_node->guid, mad_get_field64(fabric->from_node->info, 0, IB_NODE_PORT_GUID_F)); /* Make pass on switches */ if (group) { ibnd_chassis_t *ch = NULL; /* Chassis based switches first */ for (ch = fabric->chassis; ch; ch = ch->next) { int n = 0; if (!ch->chassisnum) continue; chguid = out_chassis(fabric, ch->chassisnum); chname = NULL; if (ibnd_is_xsigo_guid(chguid)) { for (node = ch->nodes; node; node = node->next_chassis_node) { if (ibnd_is_xsigo_hca(node->guid)) { chname = node->nodedesc; fprintf(f, "Hostname: %s\n", clean_nodedesc (node->nodedesc)); } } } fprintf(f, "\n# Spine Nodes"); for (n = 1; n <= SPINES_MAX_NUM; n++) { if (ch->spinenode[n]) { out_switch(ch->spinenode[n], group, chname, NULL, NULL); for (p = 1; p <= ch->spinenode[n]->numports; p++) { port = ch->spinenode[n]->ports[p]; if (port && port->remoteport) out_switch_port(port, group, NULL); } } } fprintf(f, "\n# Line Nodes"); for (n = 1; n <= LINES_MAX_NUM; n++) { if (ch->linenode[n]) { out_switch(ch->linenode[n], group, chname, NULL, NULL); for (p = 1; p <= ch->linenode[n]->numports; p++) { port = ch->linenode[n]->ports[p]; if (port && port->remoteport) out_switch_port(port, group, NULL); } } } fprintf(f, "\n# Chassis Switches"); for (node = ch->nodes; node; node = node->next_chassis_node) { if (node->type == IB_NODE_SWITCH) { out_switch(node, group, chname, NULL, NULL); for (p = 1; p <= node->numports; p++) { port = node->ports[p]; if (port && port->remoteport) out_switch_port(port, group, NULL); } } } fprintf(f, "\n# Chassis CAs"); for (node = ch->nodes; node; node = node->next_chassis_node) { if (node->type == IB_NODE_CA) { out_ca(node, group, chname, NULL, NULL); for (p = 1; p <= node->numports; p++) { port = node->ports[p]; if (port && port->remoteport) out_ca_port(port, group, NULL); } } } } } else { /* !group */ iter_user_data.group = group; iter_user_data.skip_chassis_nodes = 0; ibnd_iter_nodes_type(fabric, switch_iter_func, IB_NODE_SWITCH, &iter_user_data); } chname = NULL; if (group) { iter_user_data.group = group; iter_user_data.skip_chassis_nodes = 1; fprintf(f, "\nNon-Chassis Nodes\n"); ibnd_iter_nodes_type(fabric, switch_iter_func, IB_NODE_SWITCH, &iter_user_data); } iter_user_data.group = group; iter_user_data.skip_chassis_nodes = 0; /* Make pass on CAs */ ibnd_iter_nodes_type(fabric, ca_iter_func, IB_NODE_CA, &iter_user_data); /* Make pass on routers */ ibnd_iter_nodes_type(fabric, router_iter_func, IB_NODE_ROUTER, &iter_user_data); return i; }