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 void report_suppressed(void) { int i = 0; printf("## Suppressed:"); for (i = 0; i < sup_total; i++) printf(" %s", mad_field_name(suppressed_fields[i])); printf("\n"); }
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; }
int vsnprint_field(char *buf, size_t n, enum MAD_FIELDS f, int spacing, const char *format, va_list va_args) { int len, i, ret; len = strlen(mad_field_name(f)); if (len + 2 > n || spacing + 1 > n) return 0; strncpy(buf, mad_field_name(f), n); buf[len] = ':'; for (i = len+1; i < spacing+1; i++) { buf[i] = '.'; } ret = vsnprintf(&buf[spacing+1], n - spacing, format, va_args); if (ret >= n - spacing) buf[n] = '\0'; return ret + spacing; }
static void calculate_suppressed_fields(char *str) { enum MAD_FIELDS f; char *val, *lasts = NULL; char *tmp = strdup(str); val = strtok_r(tmp, ",", &lasts); while (val) { for (f = IB_PC_FIRST_F; f <= IB_PC_LAST_F; f++) if (strcmp(val, mad_field_name(f)) == 0) add_suppressed(f); val = strtok_r(NULL, ",", &lasts); } free(tmp); }
static void set_thres(char *name, uint32_t val) { int f; int n; char tmp[256]; for (f = IB_PC_FIRST_F; f <= IB_PC_LAST_F; f++) { if (strcmp(name, mad_field_name(f)) == 0) { mad_encode_field(thresholds, f, &val); snprintf(tmp, 255, "[%s = %u]", name, val); threshold_str = realloc(threshold_str, strlen(threshold_str)+strlen(tmp)+1); if (!threshold_str) { fprintf(stderr, "Failed to allocate memory: " "%s\n", strerror(errno)); exit(1); } n = strlen(threshold_str); strcpy(threshold_str+n, tmp); } } }
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); }
static int print_results(ib_portid_t * portid, char *node_name, ibnd_node_t * node, uint8_t * pc, int portnum, int *header_printed, uint8_t *pce, uint16_t cap_mask) { char buf[1024]; char *str = buf; uint32_t val = 0; int i, n; for (n = 0, i = IB_PC_ERR_SYM_F; i <= IB_PC_VL15_DROPPED_F; i++) { if (suppress(i)) continue; /* this is not a counter, skip it */ if (i == IB_PC_COUNTER_SELECT2_F) continue; mad_decode_field(pc, i, (void *)&val); if (exceeds_threshold(i, val)) { n += snprintf(str + n, 1024 - n, " [%s == %u]", mad_field_name(i), val); /* If there are PortXmitDiscards, get details (if supported) */ if (i == IB_PC_XMT_DISCARDS_F && details) { n += query_and_dump(str + n, sizeof(buf) - n, portid, node, node_name, portnum, "PortXmitDiscardDetails", IB_GSI_PORT_XMIT_DISCARD_DETAILS, IB_PC_RCV_LOCAL_PHY_ERR_F, IB_PC_RCV_ERR_LAST_F); /* If there are PortRcvErrors, get details (if supported) */ } else if (i == IB_PC_ERR_RCV_F && details) { n += query_and_dump(str + n, sizeof(buf) - n, portid, node, node_name, portnum, "PortRcvErrorDetails", IB_GSI_PORT_RCV_ERROR_DETAILS, IB_PC_XMT_INACT_DISC_F, IB_PC_XMT_DISC_LAST_F); } } } if (!suppress(IB_PC_XMT_WAIT_F)) { mad_decode_field(pc, IB_PC_XMT_WAIT_F, (void *)&val); if (exceeds_threshold(IB_PC_XMT_WAIT_F, val)) n += snprintf(str + n, 1024 - n, " [%s == %u]", mad_field_name(IB_PC_XMT_WAIT_F), val); } /* if we found errors. */ if (n != 0) { if (data_counters) { uint8_t *pkt = pc; int start_field = IB_PC_XMT_BYTES_F; int end_field = IB_PC_RCV_PKTS_F; if (pce) { pkt = pce; 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; } for (i = start_field; i <= end_field; i++) { uint64_t val64 = 0; float val = 0; char *unit = ""; mad_decode_field(pkt, i, (void *)&val64); if (val64) { int data = 0; 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); n += snprintf(str + n, 1024 - n, " [%s == %" PRIu64 " (%5.3f%s)]", mad_field_name(i), val64, val, unit); } } } if (!*header_printed) { if (node->type == IB_NODE_SWITCH) printf("Errors for 0x%" PRIx64 " \"%s\"\n", node->ports[0]->guid, node_name); else printf("Errors for \"%s\"\n", node_name); *header_printed = 1; summary.bad_nodes++; } if (portnum == 0xFF) { if (node->type == IB_NODE_SWITCH) printf(" GUID 0x%" PRIx64 " port ALL:%s\n", node->ports[0]->guid, str); } else { printf(" GUID 0x%" PRIx64 " port %d:%s\n", node->ports[portnum]->guid, portnum, str); if (port_config) print_port_config(node_name, node, portnum); summary.bad_ports++; } } return (n); }