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 <huan...@llnl.gov>
---
 ibsim/sim_cmd.c |  274 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 274 insertions(+)

diff --git a/ibsim/sim_cmd.c b/ibsim/sim_cmd.c
index 2da8c28..beab266 100644
--- a/ibsim/sim_cmd.c
+++ b/ibsim/sim_cmd.c
@@ -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);
 
-- 
1.7.10.3

--
To unsubscribe from this list: send the line "unsubscribe linux-rdma" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to