static void validate_width(int width, int peerwidth, int lwa) { if ((width & peerwidth & 0x8)) { if (lwa != 8) IBWARN ("Peer ports operating at active width %d rather than 8 (12x)", lwa); } else if ((width & peerwidth & 0x4)) { if (lwa != 4) IBWARN ("Peer ports operating at active width %d rather than 4 (8x)", lwa); } else if ((width & peerwidth & 0x2)) { if (lwa != 2) IBWARN ("Peer ports operating at active width %d rather than 2 (4x)", lwa); } else if ((width & peerwidth & 0x10)) { if (lwa != 16) IBWARN ("Peer ports operating at active width %d rather than 16 (2x)", lwa); } else if ((width & peerwidth & 0x1)) { if (lwa != 1) IBWARN ("Peer ports operating at active width %d rather than 1 (1x)", lwa); } }
static int _do_madrpc(int port_id, void *sndbuf, void *rcvbuf, int agentid, int len, int timeout) { uint32_t trid; /* only low 32 bits */ int retries; int length, status; if (!timeout) timeout = def_madrpc_timeout; if (ibdebug > 1) { IBWARN(">>> sending: len %d pktsz %zu", len, umad_size() + len); xdump(stderr, "send buf\n", sndbuf, umad_size() + len); } if (save_mad) { memcpy(save_mad, umad_get_mad(sndbuf), save_mad_len < len ? save_mad_len : len); save_mad = 0; } trid = mad_get_field64(umad_get_mad(sndbuf), 0, IB_MAD_TRID_F); for (retries = 0; retries < madrpc_retries; retries++) { if (retries) { ERRS("retry %d (timeout %d ms)", retries, timeout); } length = len; if (umad_send(port_id, agentid, sndbuf, length, timeout, 0) < 0) { IBWARN("send failed; %s", strerror(errno)); return -1; } /* Use same timeout on receive side just in case */ /* send packet is lost somewhere. */ do { if (umad_recv(port_id, rcvbuf, &length, timeout) < 0) { IBWARN("recv failed: %s", strerror(errno)); return -1; } if (ibdebug > 1) { IBWARN("rcv buf:"); xdump(stderr, "rcv buf\n", umad_get_mad(rcvbuf), IB_MAD_SIZE); } } while ((uint32_t)mad_get_field64(umad_get_mad(rcvbuf), 0, IB_MAD_TRID_F) != trid); status = umad_status(rcvbuf); if (!status) return length; /* done */ if (status == ENOMEM) return length; } ERRS("timeout after %d retries, %d ms", retries, timeout * retries); return -1; }
void * mad_rpc_open_port(char *dev_name, int dev_port, int *mgmt_classes, int num_classes) { struct ibmad_port *p; int port_id; if (num_classes >= MAX_CLASS) { IBWARN("too many classes %d requested", num_classes); errno = EINVAL; return NULL; } if (umad_init() < 0) { IBWARN("can't init UMAD library"); errno = ENODEV; return NULL; } p = malloc(sizeof(*p)); if (!p) { errno = ENOMEM; return NULL; } memset(p, 0, sizeof(*p)); if ((port_id = umad_open_port(dev_name, dev_port)) < 0) { IBWARN("can't open UMAD port (%s:%d)", dev_name, dev_port); if (!errno) errno = EIO; free(p); return NULL; } while (num_classes--) { int rmpp_version = 0; int mgmt = *mgmt_classes++; int agent; if (mgmt == IB_SA_CLASS) rmpp_version = 1; if (mgmt < 0 || mgmt >= MAX_CLASS || (agent = mad_register_port_client(port_id, mgmt, rmpp_version)) < 0) { IBWARN("client_register for mgmt %d failed", mgmt); if(!errno) errno = EINVAL; umad_close_port(port_id); free(p); return NULL; } p->class_agents[mgmt] = agent; } p->port_id = port_id; return p; }
void * mad_rpc_rmpp(const void *port_id, ib_rpc_t *rpc, ib_portid_t *dport, ib_rmpp_hdr_t *rmpp, void *data) { const struct ibmad_port *p = port_id; int status, len; uint8_t sndbuf[1024], rcvbuf[1024], *mad; memset(sndbuf, 0, umad_size() + IB_MAD_SIZE); DEBUG("rmpp %p data %p", rmpp, data); if ((len = mad_build_pkt(sndbuf, rpc, dport, rmpp, data)) < 0) return 0; if ((len = _do_madrpc(p->port_id, sndbuf, rcvbuf, p->class_agents[rpc->mgtclass], len, rpc->timeout)) < 0) { IBWARN("_do_madrpc failed; dport (%s)", portid2str(dport)); return 0; } mad = umad_get_mad(rcvbuf); if ((status = mad_get_field(mad, 0, IB_MAD_STATUS_F)) != 0) { ERRS("MAD completed with error status 0x%x; dport (%s)", status, portid2str(dport)); return 0; } if (ibdebug) { IBWARN("data offs %d sz %d", rpc->dataoffs, rpc->datasz); xdump(stderr, "rmpp mad data\n", mad + rpc->dataoffs, rpc->datasz); } if (rmpp) { rmpp->flags = mad_get_field(mad, 0, IB_SA_RMPP_FLAGS_F); if ((rmpp->flags & 0x3) && mad_get_field(mad, 0, IB_SA_RMPP_VERS_F) != 1) { IBWARN("bad rmpp version"); return 0; } rmpp->type = mad_get_field(mad, 0, IB_SA_RMPP_TYPE_F); rmpp->status = mad_get_field(mad, 0, IB_SA_RMPP_STATUS_F); DEBUG("rmpp type %d status %d", rmpp->type, rmpp->status); rmpp->d1.u = mad_get_field(mad, 0, IB_SA_RMPP_D1_F); rmpp->d2.u = mad_get_field(mad, 0, IB_SA_RMPP_D2_F); } if (data) memcpy(data, mad + rpc->dataoffs, rpc->datasz); rpc->recsz = mad_get_field(mad, 0, IB_SA_ATTROFFS_F); return data; }
static int sim_read_pkt(int fd, int client) { char buf[512]; Client *cl = clients + client, *dcl; int size, ret; if (client >= IBSIM_MAX_CLIENTS || !cl->pid) { IBWARN("pkt from unconnected client %d?!", client); return -1; } for (;;) { if ((size = read(fd, buf, sizeof(buf))) <= 0) return size; if ((size = process_packet(cl, buf, size, &dcl)) < 0) { IBWARN("process packet error - discarded"); continue; // not a network error } if (!dcl) continue; VERB("%s %d bytes (%zu) to client %d fd %d", dcl == cl ? "replying" : "forwarding", size, sizeof(struct sim_request), dcl->id, dcl->fd); // reply do { ret = write(dcl->fd, buf, size); } while ((errno == EAGAIN) && (ret == -1)); if (ret == size) return 0; if (ret < 0 && (errno == ECONNREFUSED || errno == ENOTCONN)) { IBWARN("client %u seems to be dead - disconnecting.", dcl->id); disconnect_client(dcl->id); } IBWARN("write failed: %m - pkt dropped"); if (dcl != cl) { /* reply timeout */ struct sim_request *r = (struct sim_request *)buf; r->status = htonl(110); ret = write(cl->fd, buf, size); } } return -1; // never reached }
static void dump_perfcounters(int extended, int timeout, uint16_t cap_mask, ib_portid_t *portid, int port, int aggregate) { char buf[1024]; if (extended != 1) { if (!port_performance_query(pc, portid, port, timeout)) IBERROR("perfquery"); if (aggregate) aggregate_perfcounters(); else mad_dump_perfcounters(buf, sizeof buf, pc, sizeof pc); } else { if (!(cap_mask & 0x200)) /* 1.2 errata: bit 9 is extended counter support */ IBWARN("PerfMgt ClassPortInfo 0x%x extended counters not indicated\n", cap_mask); if (!port_performance_ext_query(pc, portid, port, timeout)) IBERROR("perfextquery"); if (aggregate) aggregate_perfcounters_ext(); else mad_dump_perfcounters_ext(buf, sizeof buf, pc, sizeof pc); } if (!aggregate) printf("# Port counters: %s port %d\n%s", portid2str(portid), port, buf); }
/* * Callers of this function should ensure their ibmad_port has been opened with * IB_SA_CLASS as this function may require the SA to resolve addresses. */ int resolve_portid_str(char *ca_name, uint8_t ca_port, ib_portid_t * portid, char *addr_str, enum MAD_DEST dest_type, ib_portid_t *sm_id, const struct ibmad_port *srcport) { ibmad_gid_t gid; uint64_t guid; int lid; char *routepath; ib_portid_t selfportid = { 0 }; int selfport = 0; memset(portid, 0, sizeof *portid); switch (dest_type) { case IB_DEST_LID: lid = strtol(addr_str, 0, 0); if (!IB_LID_VALID(lid)) return -1; return ib_portid_set(portid, lid, 0, 0); case IB_DEST_DRPATH: if (str2drpath(&portid->drpath, addr_str, 0, 0) < 0) return -1; return 0; case IB_DEST_GUID: if (!(guid = strtoull(addr_str, 0, 0))) return -1; /* keep guid in portid? */ return resolve_guid(ca_name, ca_port, portid, &guid, sm_id, srcport); case IB_DEST_DRSLID: lid = strtol(addr_str, &routepath, 0); routepath++; if (!IB_LID_VALID(lid)) return -1; ib_portid_set(portid, lid, 0, 0); /* handle DR parsing and set DrSLID to local lid */ if (resolve_self(ca_name, ca_port, &selfportid, &selfport, NULL) < 0) return -1; if (str2drpath(&portid->drpath, routepath, selfportid.lid, 0) < 0) return -1; return 0; case IB_DEST_GID: if (inet_pton(AF_INET6, addr_str, &gid) <= 0) return -1; return resolve_gid(ca_name, ca_port, portid, gid, sm_id, srcport); default: IBWARN("bad dest_type %d", dest_type); } return -1; }
int ib_path_query_via(const struct ibmad_port *srcport, ibmad_gid_t srcgid, ibmad_gid_t destgid, ib_portid_t * sm_id, void *buf) { ib_sa_call_t sa = { 0 }; uint8_t *p; int dlid; memset(&sa, 0, sizeof sa); sa.method = IB_MAD_METHOD_GET; sa.attrid = IB_SA_ATTR_PATHRECORD; sa.mask = IB_PR_DEF_MASK; sa.trid = mad_trid(); memset(buf, 0, IB_SA_PR_RECSZ); mad_encode_field(buf, IB_SA_PR_DGID_F, destgid); mad_encode_field(buf, IB_SA_PR_SGID_F, srcgid); p = sa_rpc_call(srcport, buf, sm_id, &sa, 0); if (!p) { IBWARN("sa call path_query failed"); return -1; } mad_decode_field(p, IB_SA_PR_DLID_F, &dlid); return dlid; }
static int ca_stat(char *ca_name, int portnum, int no_ports) { umad_ca_t ca; int r; if ((r = umad_get_ca(ca_name, &ca)) < 0) return r; if (!ca.node_type) return 0; if (!no_ports && portnum >= 0) { if (portnum > ca.numports || !ca.ports[portnum]) { IBWARN("%s: '%s' has no port number %d - max (%d)", ((uint)ca.node_type <= IB_NODE_MAX ? node_type_str[ca.node_type] : "???"), ca_name, portnum, ca.numports); return -1; } printf("%s: '%s'\n", ((uint)ca.node_type <= IB_NODE_MAX ? node_type_str[ca.node_type] : "???"), ca.ca_name); port_dump(ca.ports[portnum], 1); return 0; } /* print ca header */ ca_dump(&ca); if (no_ports) return 0; for (portnum = 0; portnum <= ca.numports; portnum++) port_dump(ca.ports[portnum], 0); return 0; }
static int query_and_dump(char *buf, size_t size, ib_portid_t * portid, ibnd_node_t * node, char *node_name, int portnum, const char *attr_name, uint16_t attr_id, int start_field, int end_field) { uint8_t pc[1024]; uint32_t val = 0; int i, n; memset(pc, 0, sizeof(pc)); if (!pma_query_via(pc, portid, portnum, ibd_timeout, attr_id, ibmad_port)) { IBWARN("%s query failed on %s, %s port %d", attr_name, node_name, portid2str(portid), portnum); summary.pma_query_failures++; return 0; } for (n = 0, i = start_field; i < end_field; i++) { mad_decode_field(pc, i, (void *)&val); if (val) n += snprintf(buf + n, size - n, " [%s == %u]", mad_field_name(i), val); } return n; }
static uint8_t * pma_query_via(void *rcvbuf, ib_portid_t *dest, int port, unsigned timeout, unsigned id, const void *srcport) { ib_rpc_t rpc = {0}; int lid = dest->lid; DEBUG("lid %d port %d", lid, port); if (lid == -1) { IBWARN("only lid routed is supported"); return 0; } rpc.mgtclass = IB_PERFORMANCE_CLASS; rpc.method = IB_MAD_METHOD_GET; rpc.attr.id = id; /* Same for attribute IDs */ mad_set_field(rcvbuf, 0, IB_PC_PORT_SELECT_F, port); rpc.attr.mod = 0; rpc.timeout = timeout; rpc.datasz = IB_PC_DATA_SZ; rpc.dataoffs = IB_PC_DATA_OFFS; dest->qp = 1; if (!dest->qkey) dest->qkey = IB_DEFAULT_QP1_QKEY; if (srcport) { return mad_rpc(srcport, &rpc, dest, rcvbuf, rcvbuf); } else { return madrpc(&rpc, dest, rcvbuf, rcvbuf); } }
uint8_t *sa_rpc_call(const struct ibmad_port *ibmad_port, void *rcvbuf, ib_portid_t * portid, ib_sa_call_t * sa, unsigned timeout) { ib_rpc_t rpc = { 0 }; uint8_t *p; DEBUG("attr 0x%x mod 0x%x route %s", sa->attrid, sa->mod, portid2str(portid)); if (portid->lid <= 0) { IBWARN("only lid routes are supported"); return NULL; } rpc.mgtclass = IB_SA_CLASS; rpc.method = sa->method; rpc.attr.id = sa->attrid; rpc.attr.mod = sa->mod; rpc.mask = sa->mask; rpc.timeout = timeout; rpc.datasz = IB_SA_DATA_SIZE; rpc.dataoffs = IB_SA_DATA_OFFS; rpc.trid = sa->trid; portid->qp = 1; if (!portid->qkey) portid->qkey = IB_DEFAULT_QP1_QKEY; p = mad_rpc_rmpp(ibmad_port, &rpc, portid, 0 /*&sa->rmpp */ , rcvbuf); /* TODO: RMPP */ sa->recsz = rpc.recsz; return p; }
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 add_suppressed(enum MAD_FIELDS field) { if (sup_total >= SUP_MAX) { IBWARN("Maximum (%d) fields have been suppressed; skipping %s", sup_total, mad_field_name(field)); return; } suppressed_fields[sup_total++] = field; }
static void validate_speed(int speed, int peerspeed, int lsa) { if ((speed & 0x4) && (peerspeed & 0x4)) { if (lsa != 4) IBWARN("Peer ports operating at active speed %d rather than 4 (10.0 Gbps)", lsa); } else { if ((speed & 0x2) && (peerspeed & 0x2)) { if (lsa != 2) IBWARN("Peer ports operating at active speed %d rather than 2 (5.0 Gbps)", lsa); } else { if ((speed & 0x1) && (peerspeed & 0x1)) { if (lsa != 1) IBWARN("Peer ports operating at active speed %d rather than 1 (2.5 Gbps)", lsa); } } } }
static void validate_extended_speed(int espeed, int peerespeed, int lsea) { if ((espeed & peerespeed & 0x4)) { if (lsea != 4) IBWARN ("Peer ports operating at active extended speed %d rather than 4 (53.125 Gbps)", lsea); } else if ((espeed & peerespeed & 0x2)) { if (lsea != 2) IBWARN ("Peer ports operating at active extended speed %d rather than 2 (25.78125 Gbps)", lsea); } else if ((espeed & peerespeed & 0x1)) { if (lsea != 1) IBWARN ("Peer ports operating at active extended speed %d rather than 1 (14.0625 Gbps)", lsea); } }
static int print_errors(ib_portid_t * portid, uint16_t cap_mask, char *node_name, ibnd_node_t * node, int portnum, int *header_printed) { uint8_t pc[1024]; uint8_t pce[1024]; uint8_t *pc_ext = NULL; memset(pc, 0, 1024); memset(pce, 0, 1024); portid->sl = lid2sl_table[portid->lid]; 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 (0); } if (cap_mask & (IB_PM_EXT_WIDTH_SUPPORTED | IB_PM_EXT_WIDTH_NOIETF_SUP)) { if (!pma_query_via(pce, 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 (0); } pc_ext = pce; } if (!(cap_mask & IB_PM_PC_XMIT_WAIT_SUP)) { /* if PortCounters:PortXmitWait not supported clear this counter */ uint32_t foo = 0; mad_encode_field(pc, IB_PC_XMT_WAIT_F, &foo); } return (print_results(portid, node_name, node, pc, portnum, header_printed, pc_ext, cap_mask)); }
void * mad_rpc(const void *port_id, ib_rpc_t *rpc, ib_portid_t *dport, void *payload, void *rcvdata) { const struct ibmad_port *p = port_id; int status, len; uint8_t sndbuf[1024], rcvbuf[1024], *mad; len = 0; memset(sndbuf, 0, umad_size() + IB_MAD_SIZE); if ((len = mad_build_pkt(sndbuf, rpc, dport, 0, payload)) < 0) return 0; if ((len = _do_madrpc(p->port_id, sndbuf, rcvbuf, p->class_agents[rpc->mgtclass], len, rpc->timeout)) < 0) { IBWARN("_do_madrpc failed; dport (%s)", portid2str(dport)); return 0; } mad = umad_get_mad(rcvbuf); if ((status = mad_get_field(mad, 0, IB_DRSMP_STATUS_F)) != 0) { ERRS("MAD completed with error status 0x%x; dport (%s)", status, portid2str(dport)); return 0; } if (ibdebug) { IBWARN("data offs %d sz %d", rpc->dataoffs, rpc->datasz); xdump(stderr, "mad data\n", mad + rpc->dataoffs, rpc->datasz); } if (rcvdata) memcpy(rcvdata, mad + rpc->dataoffs, rpc->datasz); return rcvdata; }
int ib_resolve_portid_str_via(ib_portid_t *portid, char *addr_str, int dest_type, ib_portid_t *sm_id, const void *srcport) { uint64_t guid; int lid; char *routepath; ib_portid_t selfportid = {0}; int selfport = 0; switch (dest_type) { case IB_DEST_LID: lid = strtol(addr_str, 0, 0); if (!IB_LID_VALID(lid)) return -1; return ib_portid_set(portid, lid, 0, 0); case IB_DEST_DRPATH: if (str2drpath(&portid->drpath, addr_str, 0, 0) < 0) return -1; return 0; case IB_DEST_GUID: if (!(guid = strtoull(addr_str, 0, 0))) return -1; /* keep guid in portid? */ return ib_resolve_guid_via(portid, &guid, sm_id, 0, srcport); case IB_DEST_DRSLID: lid = strtol(addr_str, &routepath, 0); routepath++; if (!IB_LID_VALID(lid)) return -1; ib_portid_set(portid, lid, 0, 0); /* handle DR parsing and set DrSLID to local lid */ if (ib_resolve_self_via(&selfportid, &selfport, 0, srcport) < 0) return -1; if (str2drpath(&portid->drpath, routepath, selfportid.lid, 0) < 0) return -1; return 0; default: IBWARN("bad dest_type %d", dest_type); } return -1; }
static int mk_reply(int attr, void *data, int sz) { char *s = data; int n, i, ret = 0; switch (attr) { case IB_PING_ATTR: break; /* nothing to do here, just reply */ case IB_HOSTINFO_ATTR: if (gethostname(s, sz) < 0) snprintf(s, sz, "?hostname?"); s[sz - 1] = 0; if ((n = strlen(s)) >= sz - 1) { ret = sz; break; } s[n] = '.'; s += n + 1; sz -= n + 1; ret += n + 1; if (getdomainname(s, sz) < 0) snprintf(s, sz, "?domainname?"); if ((n = strlen(s)) == 0) s[-1] = 0; /* no domain */ else ret += n; break; case IB_CPUINFO_ATTR: s[0] = '\0'; for (i = 0; i < host_ncpu && sz > 0; i++) { n = snprintf(s, sz, "cpu %d: model %s MHZ %s\n", i, cpus[i].model, cpus[i].mhz); if (n >= sz) { IBWARN("cpuinfo truncated"); ret = sz; break; } sz -= n; s += n; ret += n; } ret++; break; default: DEBUG("unknown attr %d", attr); } return ret; }
static int sim_ctl_disconnect_client(Client * cl, struct sim_ctl * ctl) { int client = ctl->clientid; VERB("disconnecting client %d", client); if (client >= IBSIM_MAX_CLIENTS) { IBWARN("no connection for client %d", client); ctl->type = SIM_CTL_ERROR; return -1; } if (!cl->pid) { DEBUG("client %d is not connected", client); return 0; // ? } DEBUG("Detaching client %d from node \"%s\" port 0x%" PRIx64, client, cl->port->node->nodeid, cl->port->portguid); cl->pid = 0; 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; }
int build_cpuinfo(void) { char line[1024] = { 0 }, *s, *e; FILE *f; int ncpu = 0; if (!(f = fopen("/proc/cpuinfo", "r"))) { IBWARN("couldn't open /proc/cpuinfo"); return 0; } while (fgets(line, sizeof(line) - 1, f)) { if (!strncmp(line, "processor\t", 10)) { ncpu++; if (ncpu > MAX_CPUS) { fclose(f); return MAX_CPUS; } continue; } if (!ncpu || !(s = strchr(line, ':'))) continue; if ((e = strchr(s, '\n'))) *e = 0; if (!strncmp(line, "model name\t", 11)) cpus[ncpu - 1].model = strdup(s + 1); else if (!strncmp(line, "cpu MHz\t", 8)) cpus[ncpu - 1].mhz = strdup(s + 1); } fclose(f); DEBUG("ncpu %d", ncpu); return ncpu; }
uint8_t *reset_pc_ext(void *rcvbuf, ib_portid_t * dest, int port, unsigned mask, unsigned timeout, const struct ibmad_port * srcport) { ib_rpc_t rpc = { 0 }; int lid = dest->lid; DEBUG("lid %u port %d mask 0x%x", lid, port, mask); if (lid == -1) { IBWARN("only lid routed is supported"); return NULL; } if (!mask) mask = ~0; rpc.mgtclass = IB_PERFORMANCE_CLASS; rpc.method = IB_MAD_METHOD_SET; rpc.attr.id = IB_GSI_PORT_COUNTERS_EXT; memset(rcvbuf, 0, IB_MAD_SIZE); /* Same for attribute IDs */ mad_set_field(rcvbuf, 0, IB_PC_EXT_PORT_SELECT_F, port); mad_set_field(rcvbuf, 0, IB_PC_EXT_COUNTER_SELECT_F, mask); rpc.attr.mod = 0; rpc.timeout = timeout; rpc.datasz = IB_PC_DATA_SZ; rpc.dataoffs = IB_PC_DATA_OFFS; if (!dest->qp) dest->qp = 1; if (!dest->qkey) dest->qkey = IB_DEFAULT_QP1_QKEY; return mad_rpc(srcport, &rpc, dest, rcvbuf, rcvbuf); }
int ib_node_query_via(const struct ibmad_port *srcport, uint64_t guid, ib_portid_t * sm_id, void *buf) { ib_sa_call_t sa = { 0 }; uint8_t *p; memset(&sa, 0, sizeof sa); sa.method = IB_MAD_METHOD_GET; sa.attrid = IB_SA_ATTR_NODERECORD; sa.mask = IB_NR_DEF_MASK; sa.trid = mad_trid(); memset(buf, 0, IB_SA_NR_RECSZ); mad_encode_field(buf, IB_SA_NR_PORT_GUID_F, &guid); p = sa_rpc_call(srcport, buf, sm_id, &sa, 0); if (!p) { IBWARN("sa call node_query failed"); return -1; } return 0; }
static int sim_ctl(int fd) { union name_t from; socklen_t addrlen = sizeof from; struct sim_ctl ctl = { 0 }; Client *cl; if (recvfrom(fd, &ctl, sizeof(ctl), 0, (struct sockaddr *)&from, &addrlen) != sizeof(struct sim_ctl)) return -1; DEBUG("perform ctl type %d for client %s (%d)", ctl.type, get_name(&from), ctl.clientid); if (ctl.magic != SIM_MAGIC) { IBWARN("bad control pkt: magic %x (%x)", ctl.magic, SIM_MAGIC); return -1; } if (ctl.clientid >= IBSIM_MAX_CLIENTS && ctl.type != SIM_CTL_CONNECT) { IBWARN("bad client id %d", ctl.clientid); ctl.type = SIM_CTL_ERROR; return -1; } cl = clients + ctl.clientid; switch (ctl.type) { case SIM_CTL_CONNECT: sim_ctl_new_client(cl, &ctl, &from); break; case SIM_CTL_DISCONNECT: sim_ctl_disconnect_client(cl, &ctl); break; case SIM_CTL_GET_PORT: sim_ctl_get_port(cl, &ctl); break; case SIM_CTL_GET_VENDOR: sim_ctl_get_vendor(cl, &ctl); break; case SIM_CTL_GET_GID: sim_ctl_get_gid(cl, &ctl); break; case SIM_CTL_GET_GUID: sim_ctl_get_guid(cl, &ctl); break; case SIM_CTL_GET_NODEINFO: sim_ctl_get_nodeinfo(cl, &ctl); break; case SIM_CTL_GET_PORTINFO: sim_ctl_get_portinfo(cl, &ctl); break; case SIM_CTL_SET_ISSM: sim_ctl_set_issm(cl, &ctl); break; case SIM_CTL_GET_PKEYS: sim_ctl_get_pkeys(cl, &ctl); break; default: case SIM_CTL_ERROR: IBWARN("bad ctl pkt type %d", ctl.type); } if (sendto(fd, &ctl, sizeof ctl, 0, (struct sockaddr *)&from, addrlen) != sizeof ctl) { IBWARN("cannot response ctl: %m"); return -1; } return 0; }
int main(int argc, char **argv) { int mgmt_classes[3] = { IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS }; ib_portid_t portid = { 0 }; int port_op = -1; int is_switch, is_peer_switch, espeed_cap, peer_espeed_cap; int state, physstate, lwe, lws, lwa, lse, lss, lsa, lsee, lses, lsea, fdr10s, fdr10e, fdr10a; int peerlocalportnum, peerlwe, peerlws, peerlwa, peerlse, peerlss, peerlsa, peerlsee, peerlses, peerlsea, peerfdr10s, peerfdr10e, peerfdr10a; int peerwidth, peerspeed, peerespeed; uint8_t data[IB_SMP_DATA_SIZE] = { 0 }; uint8_t data2[IB_SMP_DATA_SIZE] = { 0 }; ib_portid_t peerportid = { 0 }; int portnum = 0; ib_portid_t selfportid = { 0 }; int selfport = 0; int changed = 0; int i; uint32_t vendorid, rem_vendorid; uint16_t devid, rem_devid; uint64_t val; char *endp; char usage_args[] = "<dest dr_path|lid|guid> <portnum> [<op>]\n" "\nSupported ops: enable, disable, on, off, reset, speed, espeed, fdr10,\n" "\twidth, query, down, arm, active, vls, mtu, lid, smlid, lmc,\n" "\tmkey, mkeylease, mkeyprot\n"; const char *usage_examples[] = { "3 1 disable\t\t\t# by lid", "-G 0x2C9000100D051 1 enable\t# by guid", "-D 0 1\t\t\t# (query) by direct route", "3 1 reset\t\t\t# by lid", "3 1 speed 1\t\t\t# by lid", "3 1 width 1\t\t\t# by lid", "-D 0 1 lid 0x1234 arm\t\t# by direct route", NULL }; ibdiag_process_opts(argc, argv, NULL, NULL, NULL, NULL, usage_args, usage_examples); argc -= optind; argv += optind; if (argc < 2) ibdiag_show_usage(); srcport = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 3); if (!srcport) IBEXIT("Failed to open '%s' port '%d'", ibd_ca, ibd_ca_port); smp_mkey_set(srcport, ibd_mkey); 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]); if (argc > 1) portnum = strtol(argv[1], 0, 0); for (i = 2; i < argc; i++) { int j; for (j = 0; j < NPORT_ARGS; j++) { if (strcmp(argv[i], port_args[j].name)) continue; port_args[j].set = 1; if (!port_args[j].val) { if (port_op >= 0) IBEXIT("%s only one of: ", "query, enable, disable, " "reset, down, arm, active, " "can be specified", port_args[j].name); port_op = j; break; } if (++i >= argc) IBEXIT("%s requires an additional parameter", port_args[j].name); val = strtoull(argv[i], 0, 0); switch (j) { case SPEED: if (val > 15) IBEXIT("invalid speed value %ld", val); break; case ESPEED: if (val > 31) IBEXIT("invalid extended speed value %ld", val); break; case FDR10SPEED: if (val > 1) IBEXIT("invalid fdr10 speed value %ld", val); break; case WIDTH: if ((val > 31 && val != 255)) IBEXIT("invalid width value %ld", val); break; case VLS: if (val == 0 || val > 5) IBEXIT("invalid vls value %ld", val); break; case MTU: if (val == 0 || val > 5) IBEXIT("invalid mtu value %ld", val); break; case LID: if (val == 0 || val >= 0xC000) IBEXIT("invalid lid value 0x%lx", val); break; case SMLID: if (val == 0 || val >= 0xC000) IBEXIT("invalid smlid value 0x%lx", val); break; case LMC: if (val > 7) IBEXIT("invalid lmc value %ld", val); break; case MKEY: errno = 0; val = strtoull(argv[i], &endp, 0); if (errno || *endp != '\0') { errno = 0; val = strtoull(getpass("New M_Key: "), &endp, 0); if (errno || *endp != '\0') { IBEXIT("Bad new M_Key\n"); } } /* All 64-bit values are legal */ break; case MKEYLEASE: if (val > 0xFFFF) IBEXIT("invalid mkey lease time %ld", val); break; case MKEYPROT: if (val > 3) IBEXIT("invalid mkey protection bit setting %ld", val); } *port_args[j].val = val; changed = 1; break; } if (j == NPORT_ARGS) IBEXIT("invalid operation: %s", argv[i]); } if (port_op < 0) port_op = QUERY; is_switch = get_node_info(&portid, data); vendorid = (uint32_t) mad_get_field(data, 0, IB_NODE_VENDORID_F); devid = (uint16_t) mad_get_field(data, 0, IB_NODE_DEVID_F); if ((port_args[MKEY].set || port_args[MKEYLEASE].set || port_args[MKEYPROT].set) && is_switch && portnum != 0) IBEXIT("Can't set M_Key fields on switch port != 0"); if (port_op != QUERY || changed) printf("Initial %s PortInfo:\n", is_switch ? "Switch" : "CA/RT"); else printf("%s PortInfo:\n", is_switch ? "Switch" : "CA/RT"); espeed_cap = get_port_info(&portid, data, portnum, is_switch); show_port_info(&portid, data, portnum, espeed_cap, is_switch); if (is_mlnx_ext_port_info_supported(vendorid, devid)) { get_mlnx_ext_port_info(&portid, data2, portnum); show_mlnx_ext_port_info(&portid, data2, portnum); } if (port_op != QUERY || changed) { /* * If we aren't setting the LID and the LID is the default, * the SMA command will fail due to an invalid LID. * Set it to something unlikely but valid. */ physstate = mad_get_field(data, 0, IB_PORT_PHYS_STATE_F); val = mad_get_field(data, 0, IB_PORT_LID_F); if (!port_args[LID].set && (!val || val == 0xFFFF)) mad_set_field(data, 0, IB_PORT_LID_F, 0x1234); val = mad_get_field(data, 0, IB_PORT_SMLID_F); if (!port_args[SMLID].set && (!val || val == 0xFFFF)) mad_set_field(data, 0, IB_PORT_SMLID_F, 0x1234); mad_set_field(data, 0, IB_PORT_STATE_F, 0); /* NOP */ mad_set_field(data, 0, IB_PORT_PHYS_STATE_F, 0); /* NOP */ switch (port_op) { case ON: /* Enable only if state is Disable */ if(physstate != 3) { printf("Port is already in enable state\n"); goto close_port; } case ENABLE: case RESET: /* Polling */ mad_set_field(data, 0, IB_PORT_PHYS_STATE_F, 2); break; case OFF: case DISABLE: printf("Disable may be irreversible\n"); mad_set_field(data, 0, IB_PORT_PHYS_STATE_F, 3); break; case DOWN: mad_set_field(data, 0, IB_PORT_STATE_F, 1); break; case ARM: mad_set_field(data, 0, IB_PORT_STATE_F, 3); break; case ACTIVE: mad_set_field(data, 0, IB_PORT_STATE_F, 4); break; } /* always set enabled speeds/width - defaults to NOP */ mad_set_field(data, 0, IB_PORT_LINK_SPEED_ENABLED_F, speed); mad_set_field(data, 0, IB_PORT_LINK_SPEED_EXT_ENABLED_F, espeed); mad_set_field(data, 0, IB_PORT_LINK_WIDTH_ENABLED_F, width); if (port_args[VLS].set) mad_set_field(data, 0, IB_PORT_OPER_VLS_F, vls); if (port_args[MTU].set) mad_set_field(data, 0, IB_PORT_NEIGHBOR_MTU_F, mtu); if (port_args[LID].set) mad_set_field(data, 0, IB_PORT_LID_F, lid); if (port_args[SMLID].set) mad_set_field(data, 0, IB_PORT_SMLID_F, smlid); if (port_args[LMC].set) mad_set_field(data, 0, IB_PORT_LMC_F, lmc); if (port_args[FDR10SPEED].set) { mad_set_field(data2, 0, IB_MLNX_EXT_PORT_STATE_CHG_ENABLE_F, FDR10); mad_set_field(data2, 0, IB_MLNX_EXT_PORT_LINK_SPEED_ENABLED_F, fdr10); set_mlnx_ext_port_info(&portid, data2, portnum); } if (port_args[MKEY].set) mad_set_field64(data, 0, IB_PORT_MKEY_F, mkey); if (port_args[MKEYLEASE].set) mad_set_field(data, 0, IB_PORT_MKEY_LEASE_F, mkeylease); if (port_args[MKEYPROT].set) mad_set_field(data, 0, IB_PORT_MKEY_PROT_BITS_F, mkeyprot); set_port_info(&portid, data, portnum, espeed_cap, is_switch); } else if (is_switch && portnum) { /* Now, make sure PortState is Active */ /* Or is PortPhysicalState LinkUp sufficient ? */ mad_decode_field(data, IB_PORT_STATE_F, &state); mad_decode_field(data, IB_PORT_PHYS_STATE_F, &physstate); if (state == 4) { /* Active */ mad_decode_field(data, IB_PORT_LINK_WIDTH_ENABLED_F, &lwe); mad_decode_field(data, IB_PORT_LINK_WIDTH_SUPPORTED_F, &lws); mad_decode_field(data, IB_PORT_LINK_WIDTH_ACTIVE_F, &lwa); mad_decode_field(data, IB_PORT_LINK_SPEED_SUPPORTED_F, &lss); mad_decode_field(data, IB_PORT_LINK_SPEED_ACTIVE_F, &lsa); mad_decode_field(data, IB_PORT_LINK_SPEED_ENABLED_F, &lse); mad_decode_field(data2, IB_MLNX_EXT_PORT_LINK_SPEED_SUPPORTED_F, &fdr10s); mad_decode_field(data2, IB_MLNX_EXT_PORT_LINK_SPEED_ENABLED_F, &fdr10e); mad_decode_field(data2, IB_MLNX_EXT_PORT_LINK_SPEED_ACTIVE_F, &fdr10a); if (espeed_cap) { mad_decode_field(data, IB_PORT_LINK_SPEED_EXT_SUPPORTED_F, &lses); mad_decode_field(data, IB_PORT_LINK_SPEED_EXT_ACTIVE_F, &lsea); mad_decode_field(data, IB_PORT_LINK_SPEED_EXT_ENABLED_F, &lsee); } /* Setup portid for peer port */ memcpy(&peerportid, &portid, sizeof(peerportid)); if (portid.lid == 0) { peerportid.drpath.cnt++; if (peerportid.drpath.cnt == IB_SUBNET_PATH_HOPS_MAX) { IBEXIT("Too many hops"); } } else { peerportid.drpath.cnt = 1; /* Set DrSLID to local lid */ if (resolve_self(ibd_ca, ibd_ca_port, &selfportid, &selfport, 0) < 0) IBEXIT("could not resolve self"); peerportid.drpath.drslid = (uint16_t) selfportid.lid; peerportid.drpath.drdlid = 0xffff; } peerportid.drpath.p[peerportid.drpath.cnt] = (uint8_t) portnum; /* Get peer port NodeInfo to obtain peer port number */ is_peer_switch = get_node_info(&peerportid, data); rem_vendorid = (uint32_t) mad_get_field(data, 0, IB_NODE_VENDORID_F); rem_devid = (uint16_t) mad_get_field(data, 0, IB_NODE_DEVID_F); mad_decode_field(data, IB_NODE_LOCAL_PORT_F, &peerlocalportnum); printf("Peer PortInfo:\n"); /* Get peer port characteristics */ peer_espeed_cap = get_port_info(&peerportid, data, peerlocalportnum, is_peer_switch); if (is_mlnx_ext_port_info_supported(rem_vendorid, rem_devid)) get_mlnx_ext_port_info(&peerportid, data2, peerlocalportnum); show_port_info(&peerportid, data, peerlocalportnum, peer_espeed_cap, is_peer_switch); if (is_mlnx_ext_port_info_supported(rem_vendorid, rem_devid)) show_mlnx_ext_port_info(&peerportid, data2, peerlocalportnum); mad_decode_field(data, IB_PORT_LINK_WIDTH_ENABLED_F, &peerlwe); mad_decode_field(data, IB_PORT_LINK_WIDTH_SUPPORTED_F, &peerlws); mad_decode_field(data, IB_PORT_LINK_WIDTH_ACTIVE_F, &peerlwa); mad_decode_field(data, IB_PORT_LINK_SPEED_SUPPORTED_F, &peerlss); mad_decode_field(data, IB_PORT_LINK_SPEED_ACTIVE_F, &peerlsa); mad_decode_field(data, IB_PORT_LINK_SPEED_ENABLED_F, &peerlse); mad_decode_field(data2, IB_MLNX_EXT_PORT_LINK_SPEED_SUPPORTED_F, &peerfdr10s); mad_decode_field(data2, IB_MLNX_EXT_PORT_LINK_SPEED_ENABLED_F, &peerfdr10e); mad_decode_field(data2, IB_MLNX_EXT_PORT_LINK_SPEED_ACTIVE_F, &peerfdr10a); if (peer_espeed_cap) { mad_decode_field(data, IB_PORT_LINK_SPEED_EXT_SUPPORTED_F, &peerlses); mad_decode_field(data, IB_PORT_LINK_SPEED_EXT_ACTIVE_F, &peerlsea); mad_decode_field(data, IB_PORT_LINK_SPEED_EXT_ENABLED_F, &peerlsee); } /* Now validate peer port characteristics */ /* Examine Link Width */ width = get_link_width(lwe, lws); peerwidth = get_link_width(peerlwe, peerlws); validate_width(width, peerwidth, lwa); /* Examine Link Speeds */ speed = get_link_speed(lse, lss); peerspeed = get_link_speed(peerlse, peerlss); validate_speed(speed, peerspeed, lsa); if (espeed_cap && peer_espeed_cap) { espeed = get_link_speed_ext(lsee, lses); peerespeed = get_link_speed_ext(peerlsee, peerlses); validate_extended_speed(espeed, peerespeed, lsea); } else { if (fdr10e & FDR10 && peerfdr10e & FDR10) { if (!(fdr10a & FDR10)) IBWARN("Peer ports operating at active speed %d rather than FDR10", lsa); } } } } close_port: mad_rpc_close_port(srcport); exit(0); }
static int sim_ctl_new_client(Client * cl, struct sim_ctl * ctl, union name_t *from) { union name_t name; size_t size; Node *node; struct sim_client_info *scl = (void *)ctl->data; int id = scl->id; int i; DEBUG("connecting client pid %d", id); // allocated free client for (i = 0; i < IBSIM_MAX_CLIENTS; i++) { cl = clients + i; if (!cl->pid) break; } if (i >= IBSIM_MAX_CLIENTS) { IBWARN("can't open new connection for client pid %d", id); ctl->type = SIM_CTL_ERROR; return -1; } if (scl->nodeid[0]) { if (!(node = find_node(scl->nodeid)) && !(node = find_node_by_desc(scl->nodeid))) { IBWARN("client %d attempt to attach to unknown host" " \"%s\"", i, scl->nodeid); ctl->type = SIM_CTL_ERROR; return -1; } cl->port = node_get_port(node, 0); VERB("Attaching client %d at node \"%s\" port 0x%" PRIx64, i, node->nodeid, cl->port->portguid); } else { VERB("Attaching client %d at default node \"%s\" port 0x%" PRIx64, i, default_port->node->nodeid, default_port->portguid); cl->port = default_port; } if (scl->issm && sm_exists(cl->port->node)) { IBWARN("client %d (pid %d) connection attempt failed:" " SM already exists on \"%s\"", i, id, cl->port->node->nodeid); ctl->type = SIM_CTL_ERROR; return -1; } size = make_name(&name, from->name_i.sin_addr.s_addr, id, "%s:in%d", socket_basename, id); if (connect(cl->fd, (struct sockaddr *)&name, size) < 0) IBPANIC("can't connect to in socket %s - fd %d client pid %d", get_name(&name), cl->fd, id); cl->pid = id; cl->id = i; cl->qp = scl->qp; cl->issm = scl->issm; strncpy(scl->nodeid, cl->port->node->nodeid, sizeof(scl->nodeid) - 1); scl->id = i; DEBUG("client %d (%s) is connected - fd %d", i, get_name(&name), cl->fd); return 1; }
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; }