void report(int sig) { total_time = cl_get_time_stamp() - start; DEBUG("out due signal %d", sig); printf("\n--- %s (%s) ibping statistics ---\n", last_host, portid2str(&portid)); printf("%" PRIu64 " packets transmitted, %" PRIu64 " received, %" PRIu64 "%% packet loss, time %" PRIu64 " ms\n", ntrans, replied, (lost != 0) ? lost * 100 / ntrans : 0, total_time / 1000); printf("rtt min/avg/max = %" PRIu64 ".%03" PRIu64 "/%" PRIu64 ".%03" PRIu64 "/%" PRIu64 ".%03" PRIu64 " ms\n", minrtt == ~0ull ? 0 : minrtt / 1000, minrtt == ~0ull ? 0 : minrtt % 1000, replied ? total_rtt / replied / 1000 : 0, replied ? (total_rtt / replied) % 1000 : 0, maxrtt / 1000, maxrtt % 1000); exit(0); }
static void output_aggregate_perfcounters_ext(ib_portid_t *portid) { char buf[1024]; uint32_t val = ALL_PORTS; /* set port_select to 255 to emulate AllPortSelect */ mad_encode_field(pc, IB_PC_EXT_PORT_SELECT_F, &val); mad_encode_field(pc, IB_PC_EXT_COUNTER_SELECT_F, &perf_count_ext.counterselect); mad_encode_field(pc, IB_PC_EXT_XMT_BYTES_F, &perf_count_ext.portxmitdata); mad_encode_field(pc, IB_PC_EXT_RCV_BYTES_F, &perf_count_ext.portrcvdata); mad_encode_field(pc, IB_PC_EXT_XMT_PKTS_F, &perf_count_ext.portxmitpkts); mad_encode_field(pc, IB_PC_EXT_RCV_PKTS_F, &perf_count_ext.portrcvpkts); mad_encode_field(pc, IB_PC_EXT_XMT_UPKTS_F, &perf_count_ext.portunicastxmitpkts); mad_encode_field(pc, IB_PC_EXT_RCV_UPKTS_F, &perf_count_ext.portunicastrcvpkts); mad_encode_field(pc, IB_PC_EXT_XMT_MPKTS_F, &perf_count_ext.portmulticastxmitpkits); mad_encode_field(pc, IB_PC_EXT_RCV_MPKTS_F, &perf_count_ext.portmulticastrcvpkts); mad_dump_perfcounters_ext(buf, sizeof buf, pc, sizeof pc); printf("# Port counters: %s port %d\n%s", portid2str(portid), ALL_PORTS, buf); }
static int set_port_info(ib_portid_t *dest, uint8_t *data, int portnum, int port_op) { char buf[2048]; char val[64]; if (!smp_set(data, dest, IB_ATTR_PORT_INFO, portnum, 0)) return -1; if (port_op != 4) mad_dump_portstates(buf, sizeof buf, data, sizeof data); else { mad_decode_field(data, IB_PORT_LINK_SPEED_ENABLED_F, val); mad_dump_field(IB_PORT_LINK_SPEED_ENABLED_F, buf, sizeof buf, val); sprintf(buf+strlen(buf), "%s", "\n"); } printf("\nAfter PortInfo set:\n"); printf("# Port info: %s port %d\n%s", portid2str(dest), portnum, buf); return 0; }
static int query_cap_mask(ib_portid_t * portid, char *node_name, int portnum, uint16_t * cap_mask) { uint8_t pc[1024] = { 0 }; uint16_t rc_cap_mask; /* PerfMgt ClassPortInfo is a required attribute */ if (!pma_query_via(pc, portid, portnum, ibd_timeout, CLASS_PORT_INFO, ibmad_port)) { IBWARN("classportinfo query failed on %s, %s port %d", node_name, portid2str(portid), portnum); summary.pma_query_failures++; return -1; } /* ClassPortInfo should be supported as part of libibmad */ memcpy(&rc_cap_mask, pc + 2, sizeof(rc_cap_mask)); /* CapabilityMask */ *cap_mask = rc_cap_mask; return 0; }
static int get_node(Node * node, Port * port, ib_portid_t * portid) { void *pi = port->portinfo, *ni = node->nodeinfo, *nd = node->nodedesc; char *s, *e; memset(ni, 0, sizeof(node->nodeinfo)); if (!smp_query_via(ni, portid, IB_ATTR_NODE_INFO, 0, timeout, srcport)) return -1; memset(nd, 0, sizeof(node->nodedesc)); if (!smp_query_via(nd, portid, IB_ATTR_NODE_DESC, 0, timeout, srcport)) return -1; for (s = nd, e = s + 64; s < e; s++) { if (!*s) break; if (!isprint(*s)) *s = ' '; } memset(pi, 0, sizeof(port->portinfo)); if (!smp_query_via(pi, portid, IB_ATTR_PORT_INFO, 0, timeout, srcport)) return -1; mad_decode_field(ni, IB_NODE_GUID_F, &node->nodeguid); mad_decode_field(ni, IB_NODE_TYPE_F, &node->type); mad_decode_field(ni, IB_NODE_NPORTS_F, &node->numports); mad_decode_field(ni, IB_NODE_PORT_GUID_F, &port->portguid); mad_decode_field(ni, IB_NODE_LOCAL_PORT_F, &port->portnum); mad_decode_field(pi, IB_PORT_LID_F, &port->lid); mad_decode_field(pi, IB_PORT_LMC_F, &port->lmc); mad_decode_field(pi, IB_PORT_STATE_F, &port->state); DEBUG("portid %s: got node %" PRIx64 " '%s'", portid2str(portid), node->nodeguid, node->nodedesc); return 0; }
static int get_port_info(ib_portid_t *dest, uint8_t *data, int portnum, int port_op) { char buf[2048]; char val[64]; if (!smp_query(data, dest, IB_ATTR_PORT_INFO, portnum, 0)) return -1; if (port_op != 4) { mad_dump_portstates(buf, sizeof buf, data, sizeof data); mad_decode_field(data, IB_PORT_LINK_WIDTH_SUPPORTED_F, val); mad_dump_field(IB_PORT_LINK_WIDTH_SUPPORTED_F, buf + strlen(buf), sizeof buf - strlen(buf), val); sprintf(buf+strlen(buf), "%s", "\n"); mad_decode_field(data, IB_PORT_LINK_WIDTH_ENABLED_F, val); mad_dump_field(IB_PORT_LINK_WIDTH_ENABLED_F, buf + strlen(buf), sizeof buf - strlen(buf), val); sprintf(buf+strlen(buf), "%s", "\n"); mad_decode_field(data, IB_PORT_LINK_WIDTH_ACTIVE_F, val); mad_dump_field(IB_PORT_LINK_WIDTH_ACTIVE_F, buf + strlen(buf), sizeof buf - strlen(buf), val); sprintf(buf+strlen(buf), "%s", "\n"); mad_decode_field(data, IB_PORT_LINK_SPEED_SUPPORTED_F, val); mad_dump_field(IB_PORT_LINK_SPEED_SUPPORTED_F, buf + strlen(buf), sizeof buf - strlen(buf), val); sprintf(buf+strlen(buf), "%s", "\n"); mad_decode_field(data, IB_PORT_LINK_SPEED_ENABLED_F, val); mad_dump_field(IB_PORT_LINK_SPEED_ENABLED_F, buf + strlen(buf), sizeof buf - strlen(buf), val); sprintf(buf+strlen(buf), "%s", "\n"); mad_decode_field(data, IB_PORT_LINK_SPEED_ACTIVE_F, val); mad_dump_field(IB_PORT_LINK_SPEED_ACTIVE_F, buf + strlen(buf), sizeof buf - strlen(buf), val); sprintf(buf+strlen(buf), "%s", "\n"); } else { mad_decode_field(data, IB_PORT_LINK_SPEED_ENABLED_F, val); mad_dump_field(IB_PORT_LINK_SPEED_ENABLED_F, buf, sizeof buf, val); sprintf(buf+strlen(buf), "%s", "\n"); } printf("# Port info: %s port %d\n%s", portid2str(dest), portnum, buf); return 0; }
static int switch_lookup(Switch * sw, ib_portid_t * portid, int lid) { void *si = sw->switchinfo, *fdb = sw->fdb; memset(si, 0, sizeof(sw->switchinfo)); if (!smp_query_via(si, portid, IB_ATTR_SWITCH_INFO, 0, timeout, srcport)) return -1; mad_decode_field(si, IB_SW_LINEAR_FDB_CAP_F, &sw->linearcap); mad_decode_field(si, IB_SW_LINEAR_FDB_TOP_F, &sw->linearFDBtop); if (lid >= sw->linearcap && lid > sw->linearFDBtop) return -1; memset(fdb, 0, sizeof(sw->fdb)); if (!smp_query_via(fdb, portid, IB_ATTR_LINEARFORWTBL, lid / 64, timeout, srcport)) return -1; DEBUG("portid %s: forward lid %d to port %d", portid2str(portid), lid, sw->fdb[lid % 64]); return sw->fdb[lid % 64]; }
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; }
static void show_port_info(ib_portid_t * dest, uint8_t * data, int portnum, int espeed_cap, int is_switch) { char buf[2300]; char val[64]; mad_dump_portstates(buf, sizeof buf, data, sizeof *data); mad_decode_field(data, IB_PORT_LID_F, val); mad_dump_field(IB_PORT_LID_F, buf + strlen(buf), sizeof buf - strlen(buf), val); sprintf(buf + strlen(buf), "%s", "\n"); mad_decode_field(data, IB_PORT_SMLID_F, val); mad_dump_field(IB_PORT_SMLID_F, buf + strlen(buf), sizeof buf - strlen(buf), val); sprintf(buf + strlen(buf), "%s", "\n"); mad_decode_field(data, IB_PORT_LMC_F, val); mad_dump_field(IB_PORT_LMC_F, buf + strlen(buf), sizeof buf - strlen(buf), val); sprintf(buf + strlen(buf), "%s", "\n"); mad_decode_field(data, IB_PORT_LINK_WIDTH_SUPPORTED_F, val); mad_dump_field(IB_PORT_LINK_WIDTH_SUPPORTED_F, buf + strlen(buf), sizeof buf - strlen(buf), val); sprintf(buf + strlen(buf), "%s", "\n"); mad_decode_field(data, IB_PORT_LINK_WIDTH_ENABLED_F, val); mad_dump_field(IB_PORT_LINK_WIDTH_ENABLED_F, buf + strlen(buf), sizeof buf - strlen(buf), val); sprintf(buf + strlen(buf), "%s", "\n"); mad_decode_field(data, IB_PORT_LINK_WIDTH_ACTIVE_F, val); mad_dump_field(IB_PORT_LINK_WIDTH_ACTIVE_F, buf + strlen(buf), sizeof buf - strlen(buf), val); sprintf(buf + strlen(buf), "%s", "\n"); mad_decode_field(data, IB_PORT_LINK_SPEED_SUPPORTED_F, val); mad_dump_field(IB_PORT_LINK_SPEED_SUPPORTED_F, buf + strlen(buf), sizeof buf - strlen(buf), val); sprintf(buf + strlen(buf), "%s", "\n"); mad_decode_field(data, IB_PORT_LINK_SPEED_ENABLED_F, val); mad_dump_field(IB_PORT_LINK_SPEED_ENABLED_F, buf + strlen(buf), sizeof buf - strlen(buf), val); sprintf(buf + strlen(buf), "%s", "\n"); mad_decode_field(data, IB_PORT_LINK_SPEED_ACTIVE_F, val); mad_dump_field(IB_PORT_LINK_SPEED_ACTIVE_F, buf + strlen(buf), sizeof buf - strlen(buf), val); sprintf(buf + strlen(buf), "%s", "\n"); if (espeed_cap) { mad_decode_field(data, IB_PORT_LINK_SPEED_EXT_SUPPORTED_F, val); mad_dump_field(IB_PORT_LINK_SPEED_EXT_SUPPORTED_F, buf + strlen(buf), sizeof buf - strlen(buf), val); sprintf(buf + strlen(buf), "%s", "\n"); mad_decode_field(data, IB_PORT_LINK_SPEED_EXT_ENABLED_F, val); mad_dump_field(IB_PORT_LINK_SPEED_EXT_ENABLED_F, buf + strlen(buf), sizeof buf - strlen(buf), val); sprintf(buf + strlen(buf), "%s", "\n"); mad_decode_field(data, IB_PORT_LINK_SPEED_EXT_ACTIVE_F, val); mad_dump_field(IB_PORT_LINK_SPEED_EXT_ACTIVE_F, buf + strlen(buf), sizeof buf - strlen(buf), val); sprintf(buf + strlen(buf), "%s", "\n"); } if (!is_switch || portnum == 0) { if (show_keys) { mad_decode_field(data, IB_PORT_MKEY_F, val); mad_dump_field(IB_PORT_MKEY_F, buf + strlen(buf), sizeof buf - strlen(buf), val); } else snprint_field(buf+strlen(buf), sizeof(buf)-strlen(buf), IB_PORT_MKEY_F, 32, NOT_DISPLAYED_STR); sprintf(buf+strlen(buf), "%s", "\n"); mad_decode_field(data, IB_PORT_MKEY_LEASE_F, val); mad_dump_field(IB_PORT_MKEY_LEASE_F, buf + strlen(buf), sizeof buf - strlen(buf), val); sprintf(buf+strlen(buf), "%s", "\n"); mad_decode_field(data, IB_PORT_MKEY_PROT_BITS_F, val); mad_dump_field(IB_PORT_MKEY_PROT_BITS_F, buf + strlen(buf), sizeof buf - strlen(buf), val); sprintf(buf+strlen(buf), "%s", "\n"); } printf("# Port info: %s port %d\n%s", portid2str(dest), portnum, buf); }
int main(int argc, char **argv) { int mgmt_classes[1] = { IB_SA_CLASS }; int ping_class = IB_VENDOR_OPENIB_PING_CLASS; uint64_t rtt; char *err; const struct ibdiag_opt opts[] = { {"count", 'c', 1, "<num>", "stop after count packets"}, {"flood", 'f', 0, NULL, "flood destination"}, {"oui", 'o', 1, NULL, "use specified OUI number"}, {"Server", 'S', 0, NULL, "start in server mode"}, {0} }; char usage_args[] = "<dest lid|guid>"; ibdiag_process_opts(argc, argv, NULL, "DKy", opts, process_opt, usage_args, NULL); argc -= optind; argv += optind; if (!argc && !server) ibdiag_show_usage(); srcport = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 1); if (!srcport) IBEXIT("Failed to open '%s' port '%d'", ibd_ca, ibd_ca_port); if (server) { if (mad_register_server_via(ping_class, 0, 0, oui, srcport) < 0) IBEXIT("can't serve class %d on this port", ping_class); get_host_and_domain(host_and_domain, sizeof host_and_domain); if ((err = ibping_serv())) IBEXIT("ibping to %s: %s", portid2str(&portid), err); exit(0); } if (mad_register_client_via(ping_class, 0, srcport) < 0) IBEXIT("can't register ping class %d on this port", ping_class); if (resolve_portid_str(ibd_ca, ibd_ca_port, &portid, argv[0], ibd_dest_type, ibd_sm_id, srcport) < 0) IBEXIT("can't resolve destination port %s", argv[0]); signal(SIGINT, report); signal(SIGTERM, report); start = cl_get_time_stamp(); while (count-- > 0) { ntrans++; if ((rtt = ibping(&portid, flood)) == ~0ull) { DEBUG("ibping to %s failed", portid2str(&portid)); lost++; } else { if (rtt < minrtt) minrtt = rtt; if (rtt > maxrtt) maxrtt = rtt; total_rtt += rtt; replied++; } if (!flood) sleep(1); } report(0); mad_rpc_close_port(srcport); exit(-1); }
static int print_data_cnts(ib_portid_t * portid, uint16_t cap_mask, char *node_name, ibnd_node_t * node, int portnum, int *header_printed) { uint8_t pc[1024]; int i; int start_field = IB_PC_XMT_BYTES_F; int end_field = IB_PC_RCV_PKTS_F; memset(pc, 0, 1024); portid->sl = lid2sl_table[portid->lid]; if (cap_mask & (IB_PM_EXT_WIDTH_SUPPORTED | IB_PM_EXT_WIDTH_NOIETF_SUP)) { if (!pma_query_via(pc, portid, portnum, ibd_timeout, IB_GSI_PORT_COUNTERS_EXT, ibmad_port)) { IBWARN("IB_GSI_PORT_COUNTERS_EXT query failed on %s, %s port %d", node_name, portid2str(portid), portnum); summary.pma_query_failures++; return (1); } start_field = IB_PC_EXT_XMT_BYTES_F; if (cap_mask & IB_PM_EXT_WIDTH_SUPPORTED) end_field = IB_PC_EXT_RCV_MPKTS_F; else end_field = IB_PC_EXT_RCV_PKTS_F; } else { if (!pma_query_via(pc, portid, portnum, ibd_timeout, IB_GSI_PORT_COUNTERS, ibmad_port)) { IBWARN("IB_GSI_PORT_COUNTERS query failed on %s, %s port %d", node_name, portid2str(portid), portnum); summary.pma_query_failures++; return (1); } start_field = IB_PC_XMT_BYTES_F; end_field = IB_PC_RCV_PKTS_F; } if (!*header_printed) { printf("Data Counters for 0x%" PRIx64 " \"%s\"\n", node->guid, node_name); *header_printed = 1; } if (portnum == 0xFF) printf(" GUID 0x%" PRIx64 " port ALL:", node->guid); else printf(" GUID 0x%" PRIx64 " port %d:", node->guid, portnum); for (i = start_field; i <= end_field; i++) { uint64_t val64 = 0; float val = 0; char *unit = ""; int data = 0; mad_decode_field(pc, i, (void *)&val64); if (i == IB_PC_EXT_XMT_BYTES_F || i == IB_PC_EXT_RCV_BYTES_F || i == IB_PC_XMT_BYTES_F || i == IB_PC_RCV_BYTES_F) data = 1; unit = conv_cnt_human_readable(val64, &val, data); printf(" [%s == %" PRIu64 " (%5.3f%s)]", mad_field_name(i), val64, val, unit); } printf("\n"); if (portnum != 0xFF && port_config) print_port_config(node_name, node, portnum); return (0); }
ibnd_fabric_t *ibnd_discover_fabric(char * ca_name, int ca_port, ib_portid_t * from, struct ibnd_config *cfg) { struct ibnd_config config = { 0 }; ibnd_fabric_t *fabric = NULL; ib_portid_t my_portid = { 0 }; smp_engine_t engine; ibnd_scan_t scan; int nc = 2; int mc[2] = { IB_SMI_CLASS, IB_SMI_DIRECT_CLASS }; /* If not specified start from "my" port */ if (!from) from = &my_portid; if (set_config(&config, cfg)) { IBND_ERROR("Invalid ibnd_config\n"); return NULL; } fabric = calloc(1, sizeof(*fabric)); if (!fabric) { IBND_ERROR("OOM: failed to calloc ibnd_fabric_t\n"); return NULL; } memset(fabric, 0, sizeof(*fabric)); memset(&scan.selfportid, 0, sizeof(scan.selfportid)); scan.fabric = fabric; scan.cfg = &config; scan.initial_hops = from->drpath.cnt; if (smp_engine_init(&engine, ca_name, ca_port, &scan, &config)) { free(fabric); return (NULL); } scan.ibmad_port = mad_rpc_open_port(ca_name, ca_port, mc, nc); if (!scan.ibmad_port) { IBND_ERROR("can't open MAD port (%s:%d)\n", ca_name, ca_port); smp_engine_destroy(&engine); return (NULL); } mad_rpc_set_timeout(scan.ibmad_port, cfg->timeout_ms); mad_rpc_set_retries(scan.ibmad_port, cfg->retries); smp_mkey_set(scan.ibmad_port, cfg->mkey); IBND_DEBUG("from %s\n", portid2str(from)); if (!query_node_info(&engine, from, NULL)) if (process_mads(&engine) != 0) goto error; fabric->total_mads_used = engine.total_smps; fabric->maxhops_discovered += scan.initial_hops; if (group_nodes(fabric)) goto error; smp_engine_destroy(&engine); mad_rpc_close_port(scan.ibmad_port); return fabric; error: smp_engine_destroy(&engine); mad_rpc_close_port(scan.ibmad_port); ibnd_destroy_fabric(fabric); return NULL; }
static int recv_node_info(smp_engine_t * engine, ibnd_smp_t * smp, uint8_t * mad, void *cb_data) { ibnd_scan_t *scan = engine->user_data; ibnd_fabric_t *fabric = scan->fabric; uint8_t *node_info = mad + IB_SMP_DATA_OFFS; struct ni_cbdata *ni_cbdata = (struct ni_cbdata *)cb_data; ibnd_node_t *rem_node = NULL; int rem_port_num = 0; ibnd_node_t *node; int node_is_new = 0; uint64_t node_guid = mad_get_field64(node_info, 0, IB_NODE_GUID_F); uint64_t port_guid = mad_get_field64(node_info, 0, IB_NODE_PORT_GUID_F); int port_num = mad_get_field(node_info, 0, IB_NODE_LOCAL_PORT_F); ibnd_port_t *port = NULL; if (ni_cbdata) { rem_node = ni_cbdata->node; rem_port_num = ni_cbdata->port_num; free(ni_cbdata); } node = ibnd_find_node_guid(fabric, node_guid); if (!node) { node = create_node(engine, &smp->path, node_info); if (!node) return -1; node_is_new = 1; } IBND_DEBUG("Found %s node GUID 0x%" PRIx64 " (%s)\n", node_is_new ? "new" : "old", node->guid, portid2str(&smp->path)); port = node->ports[port_num]; if (!port) { /* If we have not see this port before create a shell for it */ port = node->ports[port_num] = calloc(1, sizeof(*port)); if (!port) return -1; port->node = node; port->portnum = port_num; } port->guid = port_guid; if (scan->cfg->show_progress) dump_endnode(&smp->path, node_is_new ? "new" : "known", node, port); if (rem_node == NULL) { /* this is the start node */ fabric->from_node = node; fabric->from_portnum = port_num; } else { /* link ports... */ if (!rem_node->ports[rem_port_num]) { IBND_ERROR("Internal Error; " "Node(%p) 0x%" PRIx64 " Port %d no port created!?!?!?\n\n", rem_node, rem_node->guid, rem_port_num); return -1; } link_ports(node, port, rem_node, rem_node->ports[rem_port_num]); } if (node_is_new) { query_node_desc(engine, &smp->path, node); if (node->type == IB_NODE_SWITCH) { query_switch_info(engine, &smp->path, node); /* Query PortInfo on Switch Port 0 first */ query_port_info(engine, &smp->path, node, 0); } } if (node->type != IB_NODE_SWITCH) query_port_info(engine, &smp->path, node, port_num); return 0; }
int main(int argc, char **argv) { int mgmt_classes[3] = {IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS}; int ping_class = IB_VENDOR_OPENIB_PING_CLASS; ib_portid_t *sm_id = 0, sm_portid = {0}; int timeout = 0, udebug = 0, server = 0, flood = 0; int oui = IB_OPENIB_OUI; uint64_t rtt; unsigned count = ~0; extern int ibdebug; char *err; char *ca = 0; int ca_port = 0; static char const str_opts[] = "C:P:t:s:c:o:devGfSVhu"; static const struct option long_opts[] = { { "C", 1, 0, 'C'}, { "P", 1, 0, 'P'}, { "debug", 0, 0, 'd'}, { "err_show", 0, 0, 'e'}, { "verbose", 0, 0, 'v'}, { "Guid", 0, 0, 'G'}, { "s", 1, 0, 's'}, { "timeout", 1, 0, 't'}, { "c", 1, 0, 'c'}, { "flood", 0, 0, 'f'}, { "o", 1, 0, 'o'}, { "Server", 0, 0, 'S'}, { "Version", 0, 0, 'V'}, { "help", 0, 0, 'h'}, { "usage", 0, 0, 'u'}, { } }; argv0 = argv[0]; while (1) { int ch = getopt_long(argc, argv, str_opts, long_opts, NULL); if ( ch == -1 ) break; switch(ch) { case 'C': ca = optarg; break; case 'P': ca_port = strtoul(optarg, 0, 0); break; case 'c': count = strtoul(optarg, 0, 0); break; case 'd': ibdebug++; madrpc_show_errors(1); umad_debug(udebug); udebug++; break; case 'e': madrpc_show_errors(1); break; case 'f': flood++; break; case 'G': dest_type = IB_DEST_GUID; break; case 'o': oui = strtoul(optarg, 0, 0); break; case 's': if (ib_resolve_portid_str(&sm_portid, optarg, IB_DEST_LID, 0) < 0) IBERROR("can't resolve SM destination port %s", optarg); sm_id = &sm_portid; break; case 'S': server++; break; case 't': timeout = strtoul(optarg, 0, 0); madrpc_set_timeout(timeout); break; case 'v': verbose++; break; case 'V': fprintf(stderr, "%s %s\n", argv0, get_build_version() ); exit(-1); default: usage(); break; } } argc -= optind; argv += optind; if (!argc && !server) usage(); madrpc_init(ca, ca_port, mgmt_classes, 3); if (server) { if (mad_register_server(ping_class, 0, 0, oui) < 0) IBERROR("can't serve class %d on this port", ping_class); get_host_and_domain(host_and_domain, sizeof host_and_domain); if ((err = ibping_serv())) IBERROR("ibping to %s: %s", portid2str(&portid), err); exit(0); } if (mad_register_client(ping_class, 0) < 0) IBERROR("can't register ping class %d on this port", ping_class); if (ib_resolve_portid_str(&portid, argv[0], dest_type, sm_id) < 0) IBERROR("can't resolve destination port %s", argv[0]); signal(SIGINT, report); signal(SIGTERM, report); start = getcurrenttime(); while (count-- > 0) { ntrans++; if ((rtt = ibping(&portid, flood)) == ~0ull) { DEBUG("ibping to %s failed", portid2str(&portid)); lost++; } else { if (rtt < minrtt) minrtt = rtt; if (rtt > maxrtt) maxrtt = rtt; total_rtt += rtt; replied++; } if (!flood) sleep(1); } report(0); exit(-1); }