@@ -40,6 +40,8 @@
#include <unistd.h>
#include <ctype.h>
#include <inttypes.h>
+#include <errno.h>
+#include <limits.h>
#include <ibsim.h>
#include "sim.h"
@@ -820,6 +822,7 @@ static int dump_help(FILE * f)
"\t\t\t\tSwitchInfo : 18\n"
"\t\t\t\tPortInfo : 19\n"
);
+ fprintf(f, "\tPerformanceSet \"nodeid\"[port] [attribute].[field]=[value] : set perf. counters values\n");
fprintf(f,
"\tBaselid \"nodeid\"[port] <lid> [lmc] : change port's lid (lmc)\n");
fprintf(f, "\tVerbose [newlevel] - show/set simulator verbosity\n");
@@ -843,6 +846,275 @@ static int do_disconnect_client(FILE * out, int id)
return 0;
}
+static uint64_t check_limit(uint64_t *value, uint64_t limit)
+{
+ *value = (limit > *value? *value : limit);
+ return *value;
+}
+
+static int parse_vl_num(char *attr, char *field, int *vl)
+{
+ char *vl_ptr, *end_ptr;
+ errno = 0;
+ if(strlen(field) < strlen(attr) + 1)
+ return -1;
+ vl_ptr = field + strlen(attr);
+ *vl = (int) strtol(vl_ptr, &end_ptr, 10);
+ if(*vl == 0 && (errno != 0 || vl_ptr == end_ptr))
+ return -1;
+ else if(*vl > 15 || *vl < 0)
+ return -1;
+ return 0;
+}
+
+static int do_perf_counter_set(FILE *f, char *line)
+{
+ char *s = line, *orig, *sp, *nodeid, *attr, *field, *field_trim, *val_error;
+ Node *node;
+ int portnum, vl;
+ uint64_t value;
+ char name[NAMELEN];
+ Port *p;
+ Portcounters *pc;
+
+ if (strsep(&s, "\""))
+ orig = strsep(&s, "\"");
+
+ if (!s)
+ goto format_error;
+
+ nodeid = expand_name(orig, name, &sp);
+
+ if (!sp && *s == '[')
+ sp = s + 1;
+
+ if( !(node = find_node(nodeid))) {
+ fprintf(f, "# nodeid \"%s\" (%s) not found\n", orig, nodeid);
+ return -1;
+ }
+
+ if (sp) {
+ portnum = strtoul(sp, 0, 0);
+ if (portnum < 1 || portnum > node->numports) {
+ fprintf(f, "# bad port number %d at nodeid \"%s\"\n",
+ portnum, nodeid);
+ return -1;
+ }
+ }
+
+ if (!(p = node_get_port(node, portnum))) {
+ fprintf(f, "# port %d not found from node %s\n", portnum, nodeid);
+ return -1;
+ }
+
+ strsep(&s, " ");
+ attr = strsep(&s, ".");
+ if(s == NULL)
+ goto format_error;
+ if(attr == NULL) {
+ fprintf(f, "# attribute not found in command\n");
+ return -1;
+ }
+
+ field = strsep(&s, "=");
+ if(s == NULL)
+ goto format_error;
+ if(field == NULL) {
+ fprintf(f, "# field not found in command\n");
+ return -1;
+ }
+ field_trim = field + strlen(field) - 1;
+ while(field_trim > field && isspace(*field_trim))
+ field_trim--;
+ *(field_trim + 1) = 0;
+
+ errno = 0;
+ value = strtoull(s, &val_error, 0);
+ if((value == 0 || value == ULLONG_MAX) && errno != 0) {
+ fprintf(f, "# value is not valid integer\n");
+ return -1;
+ }
+ if(*val_error)
+ {
+ fprintf(f, "# value %s is not valid integer\n", s);
+ return -1;
+ }
+
+ pc = &(p->portcounters);
+
+ if(!strcasecmp(attr, "PortCounters"))
+ {
+ if(!strcasecmp(field, "SymbolErrorCounter"))
+ pc->errs_sym = check_limit(&value, GS_PERF_ERR_SYM_LIMIT);
+ else if(!strcasecmp(field, "LinkErrorRecoveryCounter"))
+ pc->linkrecovers = check_limit(&value, GS_PERF_LINK_RECOVERS_LIMIT);
+ else if(!strcasecmp(field, "LinkDownedCounter"))
+ pc->linkdowned = check_limit(&value, GS_PERF_LINK_DOWNED_LIMIT);
+ else if(!strcasecmp(field, "PortRcvErrors"))
+ pc->errs_rcv = check_limit(&value, GS_PERF_ERR_RCV_LIMIT);
+ else if(!strcasecmp(field, "PortRcvRemotePhysicalErrors"))
+ pc->errs_remphysrcv = check_limit(&value, GS_PERF_ERR_PHYSRCV_LIMIT);
+ else if(!strcasecmp(field, "PortRcvSwitchRelayErrors"))
+ pc->errs_rcvswitchrelay = check_limit(&value, GS_PERF_ERR_SWITCH_REL_LIMIT);
+ else if(!strcasecmp(field, "PortXmitDiscards"))
+ pc->xmitdiscards = check_limit(&value, GS_PERF_XMT_DISCARDS_LIMIT);
+ else if(!strcasecmp(field, "PortXmitConstraintErrors"))
+ pc->errs_xmtconstraint = check_limit(&value, GS_PERF_ERR_XMTCONSTR_LIMIT);
+ else if(!strcasecmp(field, "PortRcvConstraintErrors"))
+ pc->errs_rcvconstraint = check_limit(&value, GS_PERF_ERR_RCVCONSTR_LIMIT);
+ else if(!strcasecmp(field, "LocalLinkIntegrityErrors"))
+ pc->errs_localinteg = check_limit(&value, GS_PERF_ERR_LOCALINTEG_LIMIT);
+ else if(!strcasecmp(field, "ExcessiveBufferOverrunErrors"))
+ pc->errs_excessbufovrrun = check_limit(&value, GS_PERF_ERR_EXCESS_OVR_LIMIT);
+ else if(!strcasecmp(field, "VL15Dropped"))
+ pc->vl15dropped = check_limit(&value, GS_PERF_VL15_DROPPED_LIMIT);
+ else if(!strcasecmp(field, "PortXmitData"))
+ pc->flow_xmt_bytes = check_limit(&value, GS_PERF_XMT_BYTES_LIMIT);
+ else if(!strcasecmp(field, "PortRcvData"))
+ pc->flow_rcv_bytes = check_limit(&value, GS_PERF_RCV_BYTES_LIMIT);
+ else if(!strcasecmp(field, "PortXmitPkts"))
+ pc->flow_xmt_pkts = check_limit(&value, GS_PERF_XMT_PKTS_LIMIT);
+ else if(!strcasecmp(field, "PortRcvPkts"))
+ pc->flow_rcv_pkts = check_limit(&value, GS_PERF_RCV_PKTS_LIMIT);
+ else if(!strcasecmp(field, "PortXmitWait"))
+ pc->xmt_wait = check_limit(&value, GS_PERF_XMT_WAIT_LIMIT);
+ else
+ goto field_not_found;
+ }
+ else if(!strcasecmp(attr, "PortCountersExtended"))
+ {
+ if(!strcasecmp(field, "PortXmitData"))
+ pc->ext_xmit_data = check_limit(&value, UINT64_MAX);
+ else if(!strcasecmp(field, "PortRcvData"))
+ pc->ext_recv_data = check_limit(&value, UINT64_MAX);
+ else if(!strcasecmp(field, "PortXmitPkts"))
+ pc->ext_xmit_pkts = check_limit(&value, UINT64_MAX);
+ else if(!strcasecmp(field, "PortRcvPkts"))
+ pc->ext_recv_pkts = check_limit(&value, UINT64_MAX);
+ else if(!strcasecmp(field, "PortUnicastXmitPkts"))
+ pc->ext_ucast_xmit = check_limit(&value, UINT64_MAX);
+ else if(!strcasecmp(field, "PortUnicastRcvPkts"))
+ pc->ext_ucast_recv = check_limit(&value, UINT64_MAX);
+ else if(!strcasecmp(field, "PortMultiCastXmitPkts"))
+ pc->ext_mcast_xmit = check_limit(&value, UINT64_MAX);
+ else if(!strcasecmp(field, "PortMultiCastRcvPkts"))
+ pc->ext_mcast_recv = check_limit(&value, UINT64_MAX);
+ else
+ goto field_not_found;
+ }
+ else if(!strcasecmp(attr, "PortRcvErrorDetails"))
+ {
+ if(!strcasecmp(field, "PortLocalPhysicalErrors"))
+ pc->rcv_error_details.PortLocalPhysicalErrors =
+ check_limit(&value, GS_PERF_LOCAL_PHYSICAL_ERRORS_LIMIT);
+ else if(!strcasecmp(field, "PortMalformedPacketErrors"))
+ pc->rcv_error_details.PortMalformedPacketErrors =
+ check_limit(&value, GS_PERF_MALFORMED_PACKET_ERRORS_LIMIT);
+ else if(!strcasecmp(field, "PortBufferOverrunErrors"))
+ pc->rcv_error_details.PortBufferOverrunErrors =
+ check_limit(&value, GS_PERF_BUFFER_OVERRUN_ERRORS_LIMIT);
+ else if(!strcasecmp(field, "PortDLIDMappingErrors"))
+ pc->rcv_error_details.PortDLIDMappingErrors =
+ check_limit(&value, GS_PERF_DLID_MAPPING_ERRORS_LIMIT);
+ else if(!strcasecmp(field, "PortVLMappingErrors"))
+ pc->rcv_error_details.PortVLMappingErrors =
+ check_limit(&value, GS_PERF_VL_MAPPING_ERRORS_LIMIT);
+ else if(!strcasecmp(field, "PortLoopingErrors"))
+ pc->rcv_error_details.PortLoopingErrors =
+ check_limit(&value, GS_PERF_LOOPING_ERRORS_LIMIT);
+ else
+ goto field_not_found;
+ }
+ else if(!strcasecmp(attr, "PortXmitDiscardDetails"))
+ {
+ if(!strcasecmp(field, "PortInactiveDiscards"))
+ pc->xmit_discard_details.PortInactiveDiscards =
+ check_limit(&value, GS_PERF_INACTIVE_DISCARDS_LIMIT);
+ else if(!strcasecmp(field, "PortNeighborMTUDiscards"))
+ pc->xmit_discard_details.PortNeighborMTUDiscards =
+ check_limit(&value, GS_PERF_NEIGHBOR_MTU_DISCARDS_LIMIT);
+ else if(!strcasecmp(field, "PortSwLifetimeLimitDiscards"))
+ pc->xmit_discard_details.PortSwLifetimeLimitDiscards =
+ check_limit(&value, GS_PERF_SW_LIFETIME_LIMIT_DISCARDS_LIMIT);
+ else if(!strcasecmp(field, "PortSwHOQLifetimeLimitDiscards"))
+ pc->xmit_discard_details.PortSwHOQLifetimeLimitDiscards =
+ check_limit(&value, GS_PERF_SW_HOQ_LIFETIME_LIMIT_DISCARDS_LIMIT);
+ else
+ goto field_not_found;
+ }
+ else if(!strcasecmp(attr, "PortOpRcvCounters"))
+ {
+ if(!strcasecmp(field, "PortOpRcvPkts"))
+ pc->op_rcv_counters.PortOpRcvPkts = check_limit(&value,
+ GS_PERF_OP_RCV_PKTS_LIMIT);
+ else if(!strcasecmp(field, "PortOpRcvData"))
+ pc->op_rcv_counters.PortOpRcvData = check_limit(&value,
+ GS_PERF_OP_RCV_DATA_LIMIT);
+ else
+ goto field_not_found;
+ }
+ else if(!strcasecmp(attr, "PortFlowCtlCounters"))
+ {
+ if(!strcasecmp(field, "PortXmitFlowPkts"))
+ pc->flow_ctl_counters.PortXmitFlowPkts =
+ check_limit(&value, GS_PERF_XMIT_FLOW_PKTS_LIMIT);
+ else if(!strcasecmp(field, "PortRcvFlowPkts"))
+ pc->flow_ctl_counters.PortRcvFlowPkts =
+ check_limit(&value, GS_PERF_RCV_FLOW_PKTS_LIMIT);
+ else
+ goto field_not_found;
+ }
+ else if(!strcasecmp(attr, "PortVLOpPackets"))
+ {
+ if(strstr(field, "PortVLOpPackets") != field)
+ goto field_not_found;
+ if(parse_vl_num(attr, field, &vl) < 0)
+ goto field_not_found;
+ pc->vl_op_packets.PortVLOpPackets[vl] =
+ check_limit(&value, GS_PERF_VL_OP_PACKETS_LIMIT);
+ }
+ else if(!strcasecmp(attr, "PortVLOpData"))
+ {
+ if(strstr(field, "PortVLOpData") != field)
+ goto field_not_found;
+ if(parse_vl_num(attr, field, &vl) < 0)
+ goto field_not_found;
+ pc->vl_op_data.PortVLOpData[vl] =
+ check_limit(&value, GS_PERF_VL_OP_DATA_LIMIT);
+ }
+ else if(!strcasecmp(attr, "PortVLXmitFlowCtlUpdateErrors"))
+ {
+ if(strstr(field, "PortVLXmitFlowCtlUpdateErrors") != field)
+ goto field_not_found;
+ if(parse_vl_num(attr, field, &vl) < 0)
+ goto field_not_found;
+ pc->vl_xmit_flow_ctl_update_errors.PortVLXmitFlowCtlUpdateErrors[vl] =
+ check_limit(&value, GS_PERF_VL_XMIT_FLOW_CTL_UPDATE_ERRORS);
+ }
+ else if(!strcasecmp(attr, "PortVLXmitWaitCounters"))
+ {
+ if(strstr(field, "PortVLXmitWaitCounters") != field)
+ goto field_not_found;
+ if(parse_vl_num(attr, field, &vl) < 0)
+ goto field_not_found;
+ pc->vl_xmit_wait_counters.PortVLXmitWait[vl] =
+ check_limit(&value, GS_PERF_VL_XMIT_WAIT_COUNTERS_LIMIT);
+ }
+ else
+ {
+ fprintf(f, "# attribute %s cannot be found\n", attr);
+ return -1;
+ }
+ fprintf(f, "%s.%s has been set to %"PRIu64"\n", attr, field, value);
+ return 0;
+field_not_found:
+ fprintf(f, "# field %s cannot be found in attribute %s\n", field, attr);
+ return -1;
+format_error:
+ fprintf(f, "# command does not match: PerformanceSet \"nodeid\"[port] [attribute].[field]=[value]\n");
+ return -1;
+}
+
int netstarted;
int do_cmd(char *buf, FILE *f)
@@ -907,6 +1179,8 @@ int do_cmd(char *buf, FILE *f)
*/
else if (!strncasecmp(line, "ReLink", cmd_len))
r = do_relink(f, line);
+ else if (!strncasecmp(line, "PerformanceSet", cmd_len))
+ r = do_perf_counter_set(f, line);
else if (*line != '\n' && *line != '\0')
fprintf(f, "command \'%s\' unknown - skipped\n", line);
This patch requires: [PATCH 1/2] ibsim/sim.h: Add support for optional performance attributes. [PATCH 2/2] ibsim/sim_mad.c: Add read/reset functions for optional performance attributes. Use: PerformanceSet "nodeid"[port] [attribute].[field]=[value] eg. sim> PerformanceSet "S-0002c9020040fec8"[4] PortCounters.PortXmitPkts=125512 PortCounters.PortXmitPkts has been set to 125512 Add PerformanceSet command to enable setting performance counters (both required and optional fields). Signed-off-by: Perry Huang <huang32@llnl.gov> --- ibsim/sim_cmd.c | 274 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 274 insertions(+)