[Pkg-ofed-commits] [ibsim] 01/10: Imported Upstream version 0.6
Ana Beatriz Guerrero López
ana at moszumanska.debian.org
Tue Jul 1 12:41:43 UTC 2014
This is an automated email from the git hooks/post-receive script.
ana pushed a commit to branch master
in repository ibsim.
commit 6411b539b6f0e1b06b075a1b21c9fdb890af0b4a
Author: Ana Guerrero López <ana at ekaia.org>
Date: Tue Jul 1 14:15:22 2014 +0200
Imported Upstream version 0.6
---
defs.mk | 20 +-
dist.sh | 23 --
ibsim.spec | 12 +-
ibsim.spec.in | 41 ---
ibsim/ibsim.c | 32 ++-
ibsim/sim.h | 101 +++++++-
ibsim/sim_cmd.c | 285 ++++++++++++++++++++-
ibsim/sim_mad.c | 607 ++++++++++++++++++++++++++++++++++++++++----
ibsim/sim_net.c | 17 +-
tests/Makefile | 2 +-
tests/mcast_storm.c | 429 ++++++++++++++++++++------------
tests/query_many.c | 309 +++++++++++++++++++++++
tests/subnet_discover.c | 649 ++++++++++++++++++++++++++++++++++++++++++++++++
umad2sim/sim_client.c | 59 +++--
umad2sim/sim_client.h | 2 +-
umad2sim/umad2sim.c | 26 +-
16 files changed, 2251 insertions(+), 363 deletions(-)
diff --git a/defs.mk b/defs.mk
index e3b9cc4..11256c0 100644
--- a/defs.mk
+++ b/defs.mk
@@ -2,26 +2,26 @@
old_ofed:=/usr/local/ofed
prefix:= $(strip $(if $(prefix),$(prefix),\
- $(if $(wildcard $(old_ofed)/lib/libibumad.so \
+ $(if $(wildcard $(old_ofed)/lib64/libibumad.so \
$(old_ofed)/lib/libibumad.so),$(old_ofed),\
$(if $(wildcard /usr/local/lib/libibumad.so \
- /usr/local/lib/libibumad.so),/usr/local,\
- $(if $(wildcard /usr/lib /usr/lib),/usr,/tmp/unknown)))))
+ /usr/local/lib64/libibumad.so),/usr/local,\
+ $(if $(wildcard /usr/lib /usr/lib64),/usr,/tmp/unknown)))))
libpath:= $(strip $(if $(libpath),$(libpath),\
- $(if $(wildcard $(prefix)/lib/libibumad.so),\
- $(prefix)/lib,$(prefix)/lib)))
+ $(if $(wildcard $(prefix)/lib64/libibumad.so),\
+ $(prefix)/lib64,$(prefix)/lib)))
binpath:= $(if $(binpath),$(binpath),$(prefix)/bin)
-#IB_DEV_DIR:=$(HOME)/src/p
+#IB_DEV_DIR:=$(HOME)/src/m
ifdef IB_DEV_DIR
- INCS:= $(foreach l, mad umad common, -I$(IB_DEV_DIR)/libib$(l)/include) \
+ INCS:= $(foreach l, mad umad, -I$(IB_DEV_DIR)/libib$(l)/include) \
-I/usr/local/include
LIBS:= \
- $(foreach l, mad umad common, $(IB_DEV_DIR)/libib$(l)/.libs/libib$(l).so)
+ $(foreach l, mad umad, $(IB_DEV_DIR)/libib$(l)/.libs/libib$(l).so)
else
- INCS:= -I$(dir $(libpath))/include
- LIBS:= -L$(libpath) -libmad -libumad -libcommon
+ INCS:= -I$(dir $(libpath))include
+ LIBS:= -L$(libpath) -libmad -libumad
endif
CFLAGS += -Wall -g -fpic -I. -I../include $(INCS)
diff --git a/dist.sh b/dist.sh
deleted file mode 100755
index 1ec554c..0000000
--- a/dist.sh
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/bin/sh
-
-ver=`cat ibsim/ibsim.c | sed -ne '/#define IBSIM_VERSION /s/^#define IBSIM_VERSION \"\(.*\)\"/\1/p'`
-rel=1
-distdir=ibsim-${ver}
-tarball=${distdir}.tar.gz
-
-test -z "$RELEASE" || rel=$RELEASE
-
-rm -f $tarball
-rm -rf $distdir
-mkdir $distdir
-
-files=`find . -name '*.[ch]' -o -name Makefile`
-cp -a --parents $files \
- defs.mk README COPYING TODO net-examples scripts tests $distdir
-
-cat ibsim.spec.in \
- | sed -e 's/@VERSION@/'$ver'/' -e 's/@RELEASE@/'$rel'/' -e 's/@TARBALL@/'$tarball'/' \
- > $distdir/ibsim.spec
-
-tar czf $tarball $distdir
-rm -rf $distdir
diff --git a/ibsim.spec b/ibsim.spec
index 72a5d96..b65142a 100644
--- a/ibsim.spec
+++ b/ibsim.spec
@@ -1,17 +1,17 @@
-%define RELEASE 1.ofed1.4
-%define rel %{?CUSTOM_RELEASE} %{!?CUSTOM_RELEASE:%RELEASE}
+%define RELEASE 1
+%define rel %{?CUSTOM_RELEASE}%{!?CUSTOM_RELEASE:%RELEASE}
Summary: InfiniBand fabric simulator for management
Name: ibsim
-Version: 0.5
-Release: 1.ofed1.4
+Version: 0.6
+Release: %rel%{?dist}
License: GPLv2 or BSD
Group: System Environment/Libraries
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
-Source: http://www.openfabrics.org/downloads/ibsim-0.5.tar.gz
+Source: http://www.openfabrics.org/downloads/management/ibsim-0.6.tar.gz
Url: http://openfabrics.org/
-BuildRequires: libibmad-devel, libibcommon-devel, libibumad-devel
+BuildRequires: libibmad-devel, libibumad-devel
%description
ibsim provides simulation of infiniband fabric for using with OFA OpenSM, diagnostic and management tools.
diff --git a/ibsim.spec.in b/ibsim.spec.in
deleted file mode 100644
index 6c848af..0000000
--- a/ibsim.spec.in
+++ /dev/null
@@ -1,41 +0,0 @@
-
-%define RELEASE @RELEASE@
-%define rel %{?CUSTOM_RELEASE} %{!?CUSTOM_RELEASE:%RELEASE}
-
-Summary: InfiniBand fabric simulator for management
-Name: ibsim
-Version: @VERSION@
-Release: %rel%{?dist}
-License: GPLv2 or BSD
-Group: System Environment/Libraries
-BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
-Source: http://www.openfabrics.org/downloads/management/@TARBALL@
-Url: http://openfabrics.org/
-BuildRequires: libibmad-devel, libibcommon-devel, libibumad-devel
-
-%description
-ibsim provides simulation of infiniband fabric for using with OFA OpenSM, diagnostic and management tools.
-
-%prep
-%setup -q
-
-%build
-export CFLAGS="${CFLAGS:-${RPM_OPT_FLAGS}}"
-export LDFLAGS="${LDFLAGS:-${RPM_OPT_FLAGS}}"
-make prefix=%_prefix libpath=%_libdir binpath=%_bindir %{?_smp_mflags}
-
-%install
-export CFLAGS="${CFLAGS:-${RPM_OPT_FLAGS}}"
-export LDFLAGS="${LDFLAGS:-${RPM_OPT_FLAGS}}"
-make DESTDIR=${RPM_BUILD_ROOT} prefix=%_prefix libpath=%_libdir binpath=%_bindir install
-
-%clean
-rm -rf $RPM_BUILD_ROOT
-
-%files
-%defattr(-,root,root)
-%{_libdir}/umad2sim/libumad2sim*.so*
-%{_bindir}/ibsim
-%doc README COPYING TODO net-examples scripts
-
-%changelog
diff --git a/ibsim/ibsim.c b/ibsim/ibsim.c
index e399482..bc24f99 100644
--- a/ibsim/ibsim.c
+++ b/ibsim/ibsim.c
@@ -55,7 +55,7 @@
#include <ibsim.h>
#include "sim.h"
-#define IBSIM_VERSION "0.5"
+#define IBSIM_VERSION "0.6"
#undef DEBUG
#define PDEBUG if (parsedebug) IBWARN
@@ -80,6 +80,7 @@ static int maxfd;
static FILE *simout;
static int listen_to_port = IBSIM_DEFAULT_SERVER_PORT;
static int remote_mode = 0;
+static char* socket_basename;
static size_t make_name(union name_t *name, uint32_t addr, unsigned short port,
const char *fmt, ...)
@@ -109,11 +110,10 @@ static size_t make_name(union name_t *name, uint32_t addr, unsigned short port,
static char *get_name(union name_t *name)
{
- if (remote_mode) {
+ if (remote_mode)
return inet_ntoa(name->name_i.sin_addr);
- } else {
+ else
return name->name_u.sun_path + 1;
- }
}
/**
@@ -237,7 +237,7 @@ static int sim_ctl_new_client(Client * cl, struct sim_ctl * ctl, union name_t *f
}
size = make_name(&name, from->name_i.sin_addr.s_addr, id,
- "%s:in%d", SIM_BASENAME, 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",
@@ -368,7 +368,6 @@ static int sim_ctl_get_pkeys(Client * cl, struct sim_ctl * ctl)
memcpy(ctl->data, port->pkey_tbl, size);
if (size < sizeof(ctl->data))
memset(ctl->data + size, 0, sizeof(ctl->data) - size);
-
return 0;
}
@@ -547,6 +546,8 @@ int sim_cmd_file(FILE * f, char *s)
}
while (fgets(line, sizeof(line) - 1, cmd_file) != NULL) {
+ if((p = strchr(line, '\n')) != NULL)
+ *p = '\0';
do_cmd(line, f);
}
@@ -589,11 +590,14 @@ static int sim_run_console(int fd)
{
char line[128];
int ret = 0;
+ char *p = NULL;
ret = readline(fd, line, sizeof(line) - 1);
if (ret <= 0)
return ret;
+ if((p = strchr(line, '\n')) != NULL)
+ *p = '\0';
do_cmd(line, simout);
fprintf(simout, "sim%s> ", netstarted ? "" : " (inactive)");
fflush(simout);
@@ -606,7 +610,11 @@ static int sim_run(int con_fd)
fd_set rfds;
int i;
- if (sim_init_conn(SIM_BASENAME) < 0)
+ socket_basename=getenv("IBSIM_SOCKNAME");
+ if(!socket_basename)
+ socket_basename = SIM_BASENAME;
+
+ if (sim_init_conn(socket_basename) < 0)
return -1;
while (!netstarted)
@@ -646,7 +654,7 @@ int list_connections(FILE * out)
continue;
fprintf(out,
"Client %d: pid %d connected at \"%s\" port 0x%" PRIx64
- ", lid %d, qp %d %s\n", i, clients[i].pid,
+ ", lid %u, qp %d %s\n", i, clients[i].pid,
clients[i].port->node->nodeid,
clients[i].port->portguid, clients[i].port->lid,
clients[i].qp, clients[i].issm ? "SM" : "");
@@ -701,7 +709,7 @@ void usage(char *prog_name)
{
fprintf(stderr,
"Usage: %s [-f outfile -d(ebug) -p(arse_debug) -s(tart) -v(erbose) "
- "-I(gnore_duplicate) -N nodes -S switchs -P ports -L linearcap"
+ "-I(gnore_duplicate) -N nodes -S switches -P ports -L linearcap"
" -M mcastcap -r(emote_mode) -l(isten_to_port) <port>] <netfile>\n",
prog_name);
fprintf(stderr, "%s %s\n", prog_name, IBSIM_VERSION);
@@ -715,6 +723,7 @@ int main(int argc, char **argv)
extern void free_core(void);
char *outfname = 0, *netfile;
FILE *infile, *outfile;
+ int status;
static char const str_opts[] = "rf:dpvIsN:S:P:L:M:l:Vhu";
static const struct option long_opts[] = {
@@ -803,8 +812,9 @@ int main(int argc, char **argv)
IBPANIC("not enough memory for core structure");
DEBUG("initializing net \"%s\"", netfile);
- if (sim_init_net(netfile, outfile) < 0)
- IBPANIC("sim_init failed");
+ status = sim_init_net(netfile, outfile);
+ if (status < 0)
+ IBPANIC("sim_init failed, status %d", status);
sim_init_console(outfile);
diff --git a/ibsim/sim.h b/ibsim/sim.h
index b268250..daeecec 100644
--- a/ibsim/sim.h
+++ b/ibsim/sim.h
@@ -35,7 +35,6 @@
#ifndef __SIM_H__
#define __SIM_H__
-#include <infiniband/common.h>
#include <infiniband/mad.h>
#define MAXNETNODES 2048
@@ -72,7 +71,7 @@
#define MAXHOPS 16
enum NODE_TYPES {
- NO_NODE = 0,
+ NO_NODE,
HCA_NODE,
SWITCH_NODE,
ROUTER_NODE,
@@ -112,6 +111,7 @@ enum GS_PERF_COUNTER_SELECT_MASK {
GS_PERF_RCV_BYTES_MASK = (1UL << 13), // PORT_RCV_DATA
GS_PERF_XMT_PKTS_MASK = (1UL << 14), // PORT_XMIT_PKTS
GS_PERF_RCV_PKTS_MASK = (1UL << 15), // PORT_RCV_PKTS
+ GS_PERF_XMT_WAIT_MASK = (1UL << 16), // PORT_XMIT_WAIT
};
enum GS_PC_EXT_SELECT_MASK {
@@ -125,6 +125,35 @@ enum GS_PC_EXT_SELECT_MASK {
GS_PC_EXT_MCAST_RECV = 1 << 7,
};
+enum RCV_ERROR_DETAILS_COUNTER_SELECT_MASK {
+ GS_PERF_LOCAL_PHYSICAL_ERRORS_MASK = (1UL << 0), // PortLocalPhysicalErrors
+ GS_PERF_MALFORMED_PACKET_ERRORS_MASK = (1UL << 1), // PortMalformedPacketErrors
+ GS_PERF_BUFFER_OVERRUN_ERRORS_MASK = (1UL << 2), // PortBufferOverrunErrors
+ GS_PERF_DLID_MAPPING_ERRORS_MASK = (1UL << 3), // PortDLIDMappingErrors
+ GS_PERF_VL_MAPPING_ERRORS_MASK = (1UL << 4), // PortVLMappingErrors
+ GS_PERF_LOOPING_ERRORS_MASK = (1UL << 5), // PortLoopingErrors
+};
+
+enum XMIT_DISCARD_DETAILS_SELECT_MASK {
+ GS_PERF_INACTIVE_DISCARDS_MASK = (1UL << 0), // PortInactiveDiscards
+ GS_PERF_NEIGHBOR_MTU_DISCARDS_MASK = (1UL << 1), // PortNeighborMTUDiscards
+ GS_PERF_SW_LIFETIME_LIMIT_DISCARDS_MASK = (1UL << 2), // PortSwLifetimeLimitDiscards
+ GS_PERF_SW_HOQ_LIFETIME_LIMIT_DISCARDS_MASK = (1UL << 3), // PortSwHOQLifetimeLimitDiscards
+};
+
+enum OP_RCV_COUNTERS_SELECT_MASK {
+ GS_PERF_OP_RCV_PKTS_MASK = (1UL << 0), // PortOpRcvPkts
+ GS_PERF_OP_RCV_DATA_MASK = (1UL << 1), // PortOpRcvData
+};
+
+enum FLOW_CTL_COUNTERS_SELECT_MASK {
+ GS_PERF_XMIT_FLOW_PKTS_MASK = (1UL << 0), // PortXmitFlowPkts
+ GS_PERF_RCV_FLOW_PKTS_MASK = (1UL << 1), // PortRcvFlowPkts
+};
+
+/* Counter select bit masks for PortVLOpPackets[0-15], PortVLOpData[0-15],
+and PortVLXmitWaitCounters[0-15] are ommitted due to redundency. */
+
enum GS_PERF_COUNTER_SELECT_LIMIT {
GS_PERF_ERR_SYM_LIMIT = 0xffff,
GS_PERF_LINK_RECOVERS_LIMIT = 0xff,
@@ -142,6 +171,25 @@ enum GS_PERF_COUNTER_SELECT_LIMIT {
GS_PERF_RCV_BYTES_LIMIT = 0xffffffff,
GS_PERF_XMT_PKTS_LIMIT = 0xffffffff,
GS_PERF_RCV_PKTS_LIMIT = 0xffffffff,
+ GS_PERF_XMT_WAIT_LIMIT = 0xffffffff,
+ GS_PERF_LOCAL_PHYSICAL_ERRORS_LIMIT = 0xffff, // PortLocalPhysicalErrors
+ GS_PERF_MALFORMED_PACKET_ERRORS_LIMIT = 0xffff, // PortMalformedPacketErrors
+ GS_PERF_BUFFER_OVERRUN_ERRORS_LIMIT = 0xffff, // PortBufferOverrunErrors
+ GS_PERF_DLID_MAPPING_ERRORS_LIMIT = 0xffff, // PortDLIDMappingErrors
+ GS_PERF_VL_MAPPING_ERRORS_LIMIT = 0xffff, // PortVLMappingErrors
+ GS_PERF_LOOPING_ERRORS_LIMIT = 0xffff, // PortLoopingErrors
+ GS_PERF_INACTIVE_DISCARDS_LIMIT = 0xffff, // PortInactiveDiscards
+ GS_PERF_NEIGHBOR_MTU_DISCARDS_LIMIT = 0xffff, // PortNeighborMTUDiscards
+ GS_PERF_SW_LIFETIME_LIMIT_DISCARDS_LIMIT = 0xffff, // PortSwLifetimeLimitDiscards
+ GS_PERF_SW_HOQ_LIFETIME_LIMIT_DISCARDS_LIMIT = 0xffff, // PortSwHOQLifetimeLimitDiscards
+ GS_PERF_OP_RCV_PKTS_LIMIT = 0xffffffff, // PortOpRcvPkts
+ GS_PERF_OP_RCV_DATA_LIMIT = 0xffffffff, // PortOpRcvData
+ GS_PERF_XMIT_FLOW_PKTS_LIMIT = 0xffffffff, // PortXmitFlowPkts
+ GS_PERF_RCV_FLOW_PKTS_LIMIT = 0xffffffff, // PortRcvFlowPkts
+ GS_PERF_VL_OP_PACKETS_LIMIT = 0xffff, // PortVLOpPackets[0-15]
+ GS_PERF_VL_OP_DATA_LIMIT = 0xffffffff, // PortVLOpData[0-15]
+ GS_PERF_VL_XMIT_FLOW_CTL_UPDATE_ERRORS = 0x3, // PortVLXmitFlowCtlUpdateErrors[0-15]
+ GS_PERF_VL_XMIT_WAIT_COUNTERS_LIMIT = 0xffff, // PortVLXmitWaitCounters[0-15]
};
typedef struct Port Port;
@@ -183,6 +231,49 @@ struct Portcounters {
uint8_t errs_rcvconstraint;
uint16_t errs_rcvswitchrelay;
uint8_t errs_excessbufovrrun;
+ uint32_t xmt_wait;
+
+ struct PortRcvErrorDetails {
+ uint16_t PortLocalPhysicalErrors;
+ uint16_t PortMalformedPacketErrors;
+ uint16_t PortBufferOverrunErrors;
+ uint16_t PortDLIDMappingErrors;
+ uint16_t PortVLMappingErrors;
+ uint16_t PortLoopingErrors;
+ } rcv_error_details;
+
+ struct PortXmitDiscardDetails {
+ uint16_t PortInactiveDiscards;
+ uint16_t PortNeighborMTUDiscards;
+ uint16_t PortSwLifetimeLimitDiscards;
+ uint16_t PortSwHOQLifetimeLimitDiscards;
+ } xmit_discard_details;
+
+ struct PortOpRcvCounters {
+ uint32_t PortOpRcvPkts;
+ uint32_t PortOpRcvData;
+ } op_rcv_counters;
+
+ struct PortFlowCtlCounters {
+ uint32_t PortXmitFlowPkts;
+ uint32_t PortRcvFlowPkts;
+ } flow_ctl_counters;
+
+ struct PortVLOpPackets {
+ uint16_t PortVLOpPackets[16];
+ } vl_op_packets;
+
+ struct PortVLOpData {
+ uint32_t PortVLOpData[16];
+ } vl_op_data;
+
+ struct PortVLXmitFlowCtlUpdateErrors {
+ uint8_t PortVLXmitFlowCtlUpdateErrors[16];
+ } vl_xmit_flow_ctl_update_errors;
+
+ struct PortVLXmitWaitCounters {
+ uint16_t PortVLXmitWait[16];
+ } vl_xmit_wait_counters;
};
struct Port {
@@ -198,8 +289,8 @@ struct Port {
int physstate;
int lmc;
int hoqlife;
- uint8_t op_vls;
uint8_t portinfo[64];
+ uint8_t op_vls;
char remotenodeid[NODEIDLEN];
char remotealias[ALIASLEN + 1];
@@ -287,10 +378,10 @@ void *sim_cmd_thread(void *file);
// sim_mad.c
int process_packet(Client * cl, void *p, int size, Client ** dcl);
-int send_trap(Port * port, int trapnum);
+int send_trap(Port * port, unsigned trapnum);
extern Port *default_port;
-extern int simverb, modified;
+extern int simverb;
extern int netstarted;
#endif /* __SIM_H__ */
diff --git a/ibsim/sim_cmd.c b/ibsim/sim_cmd.c
index dd9384e..4822a0b 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"
@@ -203,7 +205,8 @@ static int do_relink(FILE * f, char *line)
return -1;
}
- rport = node_get_port(lport->previous_remotenode, lport->previous_remoteport);
+ rport = node_get_port(lport->previous_remotenode,
+ lport->previous_remoteport);
if (link_ports(lport, rport) < 0)
return -fprintf(f,
@@ -220,7 +223,8 @@ static int do_relink(FILE * f, char *line)
if (!lport->previous_remotenode)
continue;
- rport = node_get_port(lport->previous_remotenode, lport->previous_remoteport);
+ rport = node_get_port(lport->previous_remotenode,
+ lport->previous_remoteport);
if (link_ports(lport, rport) < 0)
continue;
@@ -286,14 +290,14 @@ static int do_seterror(FILE * f, char *line)
char *s = line;
char *nodeid = 0, name[NAMELEN], *sp, *orig = 0;
int portnum = -1; // def - all ports
- int numports, set = 0, rate = 0;
+ int startport, numports, set = 0, rate = 0;
uint16_t attr = 0;
if (strsep(&s, "\""))
orig = strsep(&s, "\"");
if (!s) {
- fprintf(f, "# unlink: bad parameter in \"%s\"\n", line);
+ fprintf(f, "# set error: bad parameter in \"%s\"\n", line);
return -1;
}
@@ -307,8 +311,12 @@ static int do_seterror(FILE * f, char *line)
}
if (sp) {
+ if (node->type == SWITCH_NODE)
+ startport = 0;
+ else
+ startport = 1;
portnum = strtoul(sp, 0, 0);
- if (portnum < 1 || portnum > node->numports) {
+ if (portnum < startport || portnum > node->numports) {
fprintf(f, "# bad port number %d at nodeid \"%s\"\n",
portnum, nodeid);
return -1;
@@ -541,7 +549,7 @@ static void dump_port(FILE * f, Port * port, int type)
PORTSTATE(port->state), PHYSSTATE(port->physstate),
comment);
else
- fprintf(f, "\t lid %d lmc %d smlid %d %s %s %s/%s%s\n",
+ fprintf(f, "\t lid %u lmc %d smlid %u %s %s %s/%s%s\n",
port->lid, port->lmc, port->smlid,
PORTLINKWIDTH(port->linkwidth),
PORTLINKSPEED(port->linkspeed),
@@ -578,9 +586,8 @@ static int dump_net(FILE * f, char *line)
nports++;
dump_switch(f, node->sw);
}
- for (i = 0; i < nports; i++) {
+ for (i = 0; i < nports; i++)
dump_port(f, ports + node->portsbase + i, node->type);
- }
nnodes++;
}
@@ -714,7 +721,7 @@ static int dump_route(FILE * f, char *line)
node = fromport->node;
port = fromport;
portnum = port->portnum;
- fprintf(f, "From node \"%s\" port %d lid %d\n", node->nodeid, portnum,
+ fprintf(f, "From node \"%s\" port %d lid %u\n", node->nodeid, portnum,
from);
while (maxhops--) {
if (port->state != 4)
@@ -749,7 +756,7 @@ static int dump_route(FILE * f, char *line)
fprintf(f, "no route found after %d hops\n", MAXHOPS);
return -1;
}
- fprintf(f, "To node \"%s\" port %d lid %d\n", node->nodeid, portnum,
+ fprintf(f, "To node \"%s\" port %d lid %u\n", node->nodeid, portnum,
to);
return 0;
@@ -798,7 +805,7 @@ static int dump_help(FILE * f)
fprintf(f, "sim> Commands:\n");
fprintf(f, "\t!<filename> - run commands from the file\n");
fprintf(f, "\tStart network\n");
- fprintf(f, "\tDump [nodeid] (def all network)\n");
+ fprintf(f, "\tDump [\"nodeid\"] : dump node information in network\n");
fprintf(f, "\tRoute <from-lid> <to-lid>\n");
fprintf(f, "\tLink \"nodeid\"[port] \"remoteid\"[port]\n");
fprintf(f, "\tReLink \"nodeid\" : restore previously unconnected link(s) of the node\n");
@@ -817,8 +824,9 @@ static int dump_help(FILE * f)
"\t\t\t\tNodeDescription : 16\n"
"\t\t\t\tNodeInfo : 17\n"
"\t\t\t\tSwitchInfo : 18\n"
- "\t\t\t\tPortInfo : 19\n"
+ "\t\t\t\tPortInfo : 21\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");
@@ -842,6 +850,255 @@ 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;
+ }
+
+ if (s && *s)
+ while (isspace(*s))
+ 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 not 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)
@@ -856,7 +1113,7 @@ int do_cmd(char *buf, FILE *f)
cmd_len++;
if (*line == '#')
- fprintf(f, line);
+ fprintf(f, "%s", line);
else if (*line == '!')
r = sim_cmd_file(f, line);
else if (!strncasecmp(line, "Dump", cmd_len))
@@ -906,6 +1163,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);
diff --git a/ibsim/sim_mad.c b/ibsim/sim_mad.c
index f530a7a..223d507 100644
--- a/ibsim/sim_mad.c
+++ b/ibsim/sim_mad.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2004-2008 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2009 HNR Consulting. All rights reserved.
*
* This file is part of ibsim.
*
@@ -58,7 +59,10 @@ typedef int (EncodeTrapfn) (Port * port, char *data);
static Smpfn do_nodeinfo, do_nodedesc, do_switchinfo, do_portinfo,
do_linearforwtbl, do_multicastforwtbl, do_portcounters, do_extcounters,
- do_pkeytbl, do_sl2vl, do_vlarb, do_guidinfo, do_nothing;
+ do_rcv_error_details, do_xmit_discard_details, do_op_rcv_counters,
+ do_flow_ctl_counters, do_vl_op_packets, do_vl_op_data,
+ do_vl_xmit_flow_ctl_update_errors, do_vl_xmit_wait_counters, do_pkeytbl,
+ do_sl2vl, do_vlarb, do_guidinfo, do_cpi;
static EncodeTrapfn encode_trap128;
static EncodeTrapfn encode_trap144;
@@ -78,14 +82,21 @@ static Smpfn *attrs[IB_PERFORMANCE_CLASS + 1][0xff] = {
[IB_ATTR_LAST] 0,
},
- [IB_PERFORMANCE_CLASS] {[CLASS_PORT_INFO] = do_nothing,
+ [IB_PERFORMANCE_CLASS] {[CLASS_PORT_INFO] = do_cpi,
[IB_GSI_PORT_SAMPLES_CONTROL] = 0,
[IB_GSI_PORT_SAMPLES_RESULT] = 0,
[IB_GSI_PORT_COUNTERS] = do_portcounters,
[IB_GSI_PORT_COUNTERS_EXT] = do_extcounters,
+ [IB_GSI_PORT_RCV_ERROR_DETAILS] = do_rcv_error_details,
+ [IB_GSI_PORT_XMIT_DISCARD_DETAILS] = do_xmit_discard_details,
+ [IB_GSI_PORT_PORT_OP_RCV_COUNTERS] = do_op_rcv_counters,
+ [IB_GSI_PORT_PORT_FLOW_CTL_COUNTERS] = do_flow_ctl_counters,
+ [IB_GSI_PORT_PORT_VL_OP_PACKETS] = do_vl_op_packets,
+ [IB_GSI_PORT_PORT_VL_OP_DATA] = do_vl_op_data,
+ [IB_GSI_PORT_PORT_VL_XMIT_FLOW_CTL_UPDATE_ERRORS] = do_vl_xmit_flow_ctl_update_errors,
+ [IB_GSI_PORT_PORT_VL_XMIT_WAIT_COUNTERS] = do_vl_xmit_wait_counters,
[IB_GSI_ATTR_LAST] 0,
-
},
};
@@ -94,7 +105,6 @@ static EncodeTrapfn *encodetrap[] = {
[TRAP_144] encode_trap144,
[TRAP_NUM_LAST] 0,
-
};
extern Node *nodes;
@@ -104,6 +114,10 @@ extern Port **lids;
extern int netnodes, netports, netswitches;
extern int maxlinearcap;
+typedef void (*pc_reset_function)(Portcounters * pc, unsigned mask);
+typedef void (*pc_get_function)(Portcounters * pc, uint8_t * data);
+typedef void (*pc_sum_function)(Portcounters * totals, Portcounters * pc);
+
static uint64_t update_trid(uint8_t *mad, unsigned response, Client *cl)
{
uint64_t trid = mad_get_field64(mad, 0, IB_MAD_TRID_F);
@@ -219,16 +233,29 @@ static int reply_MAD(void *buf, ib_rpc_t * rpc, ib_dr_path_t * path,
return 0;
}
-static int do_nothing(Port * port, unsigned op, uint32_t mod, uint8_t * data)
+static int do_cpi(Port * port, unsigned op, uint32_t mod, uint8_t * data)
{
- return 0;
+ Node *node = port->node;
+ int status = 0;
+
+ if (op != IB_MAD_METHOD_GET)
+ status = ERR_METHOD_UNSUPPORTED;
+ memset(data, 0, IB_SMP_DATA_SIZE);
+ mad_set_field(data, 0, IB_CPI_BASEVER_F, 1);
+ mad_set_field(data, 0, IB_CPI_CLASSVER_F, 1);
+ if (node->type != SWITCH_NODE)
+ mad_set_field(data, 0, IB_CPI_CAPMASK_F, 0x200);
+ else
+ mad_set_field(data, 0, IB_CPI_CAPMASK_F, 0x300);
+ mad_set_field(data, 0, IB_CPI_RESP_TIME_VALUE_F, 0x12);
+ return status;
}
static int do_nodedesc(Port * port, unsigned op, uint32_t mod, uint8_t * data)
{
int status = 0;
- if (op != 1) // get
+ if (op != IB_MAD_METHOD_GET)
status = ERR_METHOD_UNSUPPORTED;
memcpy(data, port->node->nodedesc, IB_SMP_DATA_SIZE);
@@ -241,7 +268,7 @@ static int do_nodeinfo(Port * port, unsigned op, uint32_t mod, uint8_t * data)
int status = 0;
uint64_t portguid = node->nodeguid + port->portnum;
- if (op != IB_MAD_METHOD_GET) // get
+ if (op != IB_MAD_METHOD_GET)
status = ERR_METHOD_UNSUPPORTED;
memcpy(data, node->nodeinfo, IB_SMP_DATA_SIZE);
@@ -261,7 +288,7 @@ static int do_switchinfo(Port * port, unsigned op, uint32_t mod, uint8_t * data)
if (!sw) // not a Switch?
return ERR_ATTR_UNSUPPORTED;
- if (op == 2) { // Set
+ if (op == IB_MAD_METHOD_SET) {
if (mad_get_field(data, 0, IB_SW_STATE_CHANGE_F))
sw->portchange = 0;
sw->linearFDBtop =
@@ -327,11 +354,10 @@ static int do_sl2vl(Port * port, unsigned op, uint32_t mod, uint8_t * data)
sl2vl = port->sl2vl + 8 * n;
- if (op == IB_MAD_METHOD_SET) {
+ if (op == IB_MAD_METHOD_SET)
memcpy(sl2vl, data, 8);
- } else {
+ else
memcpy(data, sl2vl, 8);
- }
return 0;
}
@@ -366,10 +392,10 @@ static int do_vlarb(Port * port, unsigned op, uint32_t mod, uint8_t * data)
size *= sizeof(*vlarb);
- if (op == IB_MAD_METHOD_SET) {
+ if (op == IB_MAD_METHOD_SET)
memcpy(vlarb, data, size);
- } else {
- memset(data, 0, 64);
+ else {
+ memset(data, 0, IB_SMP_DATA_SIZE);
memcpy(data, vlarb, size);
}
@@ -385,7 +411,7 @@ static int do_guidinfo(Port * port, unsigned op, uint32_t mod, uint8_t * data)
if (op != IB_MAD_METHOD_GET) // only get currently supported (non compliant)
status = ERR_METHOD_UNSUPPORTED;
- memset(data, 0, 64);
+ memset(data, 0, IB_SMP_DATA_SIZE);
if (mod == 0) {
if (node->type == SWITCH_NODE)
mad_encode_field(data, IB_GUID_GUID0_F, &node->nodeguid);
@@ -413,7 +439,7 @@ do_portinfo(Port * port, unsigned op, uint32_t portnum, uint8_t * data)
DEBUG("in node %" PRIx64 " port %" PRIx64 ": port %" PRIx64 " (%d(%d))",
node->nodeguid, port->portguid, p->portguid, p->portnum, portnum);
- if (op == IB_MAD_METHOD_SET) { // set
+ if (op == IB_MAD_METHOD_SET) {
unsigned val;
if (node->type != SWITCH_NODE && port->portnum != p->portnum)
return ERR_BAD_PARAM; // on HCA or rtr can't "set" on other port
@@ -459,7 +485,7 @@ do_portinfo(Port * port, unsigned op, uint32_t portnum, uint8_t * data)
if (p->lid > 0 && p->lid < maxlinearcap
&& lids[p->lid] != p && lids[p->lid])
IBWARN
- ("Port %s:%d overwrite lid table entry for lid %d (was %s:%d)",
+ ("Port %s:%d overwrite lid table entry for lid %u (was %s:%d)",
node->nodeid, p->portnum, p->lid,
lids[p->lid]->node->nodeid,
lids[p->lid]->portnum);
@@ -473,6 +499,7 @@ do_portinfo(Port * port, unsigned op, uint32_t portnum, uint8_t * data)
update_portinfo(p);
memcpy(data, p->portinfo, IB_SMP_DATA_SIZE);
+ mad_set_field(data, 0, IB_PORT_LOCAL_PORT_F, port->portnum);
return 0;
}
@@ -488,10 +515,9 @@ static int do_linearforwtbl(Port * port, unsigned op, uint32_t mod,
if (mod < 0 || mod > 767)
return ERR_BAD_PARAM;
- if (op == IB_MAD_METHOD_SET) { // Set
+ if (op == IB_MAD_METHOD_SET)
mad_get_array(data, 0, IB_LINEAR_FORW_TBL_F,
sw->fdb + mod * 64);
- }
mad_set_array(data, 0, IB_LINEAR_FORW_TBL_F, sw->fdb + mod * 64);
@@ -518,16 +544,15 @@ static int do_multicastforwtbl(Port * port, unsigned op, uint32_t mod,
}
blockposition = (numBlock32 * NUMBEROFPORTMASK + numPortMsk) * 64;
- if (op == IB_MAD_METHOD_SET) { // Set
+ if (op == IB_MAD_METHOD_SET)
mad_get_array(data, 0, IB_MULTICAST_FORW_TBL_F,
sw->mfdb + blockposition);
- }
mad_set_array(data, 0, IB_MULTICAST_FORW_TBL_F,
sw->mfdb + blockposition);
return 0;
}
-static void pc_reset(Portcounters * pc, uint mask)
+static void pc_reset(Portcounters * pc, unsigned mask)
{
if (mask & GS_PERF_ERR_SYM_MASK)
pc->errs_sym = 0;
@@ -561,6 +586,8 @@ static void pc_reset(Portcounters * pc, uint mask)
pc->flow_xmt_pkts = 0;
if (mask & GS_PERF_RCV_PKTS_MASK)
pc->flow_rcv_pkts = 0;
+ if (mask & GS_PERF_XMT_WAIT_MASK)
+ pc->xmt_wait = 0;
}
static inline uint32_t addval(uint32_t val, uint32_t delta, uint32_t max)
@@ -603,7 +630,7 @@ static int pc_updated(Port ** srcport, Port * destport)
uint32_t madsize_div_4 = 72; //real data divided by 4
if (*srcport != destport) {
- //PKT get out of port ..
+ //PKT got out of port ..
srcpc->flow_xmt_pkts =
addval(srcpc->flow_xmt_pkts, 1, GS_PERF_XMT_PKTS_LIMIT);
srcpc->flow_xmt_bytes =
@@ -619,7 +646,7 @@ static int pc_updated(Port ** srcport, Port * destport)
VERB("drop pkt due error rate %d", destport->errrate);
return 0;
}
- //PKT get in to the port ..
+ //PKT got into the port ..
destpc->flow_rcv_pkts =
addval(destpc->flow_rcv_pkts, 1, GS_PERF_RCV_PKTS_LIMIT);
destpc->flow_rcv_bytes =
@@ -635,6 +662,9 @@ static int pc_updated(Port ** srcport, Port * destport)
static void pc_sum(Portcounters * totals, Portcounters * pc)
{
+ totals->xmt_wait =
+ addval(totals->xmt_wait, pc->xmt_wait,
+ GS_PERF_XMT_WAIT_LIMIT);
totals->flow_xmt_pkts =
addval(totals->flow_xmt_pkts, pc->flow_xmt_pkts,
GS_PERF_XMT_PKTS_LIMIT);
@@ -685,6 +715,7 @@ static void pc_sum(Portcounters * totals, Portcounters * pc)
static void pc_get(Portcounters * pc, uint8_t * data)
{
+ mad_set_field(data, 0, IB_PC_XMT_WAIT_F, pc->xmt_wait);
mad_set_field(data, 0, IB_PC_XMT_PKTS_F, pc->flow_xmt_pkts);
mad_set_field(data, 0, IB_PC_XMT_BYTES_F, pc->flow_xmt_bytes);
mad_set_field(data, 0, IB_PC_RCV_PKTS_F, pc->flow_rcv_pkts);
@@ -710,7 +741,7 @@ static int do_portcounters(Port * port, unsigned op, uint32_t unused,
Node *node = port->node;
int portnum = mad_get_field(data, 0, IB_PC_PORT_SELECT_F);
Portcounters totals;
- uint mask;
+ unsigned mask, mask2;
Port *p;
int i;
@@ -725,6 +756,9 @@ static int do_portcounters(Port * port, unsigned op, uint32_t unused,
node->nodeguid, port->portguid, portnum);
mask = mad_get_field(data, 0, IB_PC_COUNTER_SELECT_F);
+ mask2 = mad_get_field(data, 0, IB_PC_COUNTER_SELECT2_F);
+ if (mask2)
+ mask |= GS_PERF_XMT_WAIT_MASK;
if (portnum != 0xff) {
if (!(p = node_get_port(node, portnum)))
@@ -740,13 +774,10 @@ static int do_portcounters(Port * port, unsigned op, uint32_t unused,
memset(&totals, 0, sizeof totals);
for (i = 0; i <= node->numports; i++) {
-
if (!(p = node_get_port(node, i)))
return ERR_BAD_PARAM;
-
if (op == IB_MAD_METHOD_SET)
pc_reset(&p->portcounters, mask);
-
pc_sum(&totals, &p->portcounters);
}
@@ -766,7 +797,7 @@ static void pc_ext_sum(Portcounters * total, Portcounters * pc)
ADDVAL64(total->ext_mcast_recv, pc->ext_mcast_recv);
}
-static void pc_ext_reset(Portcounters * pc, uint mask)
+static void pc_ext_reset(Portcounters * pc, unsigned mask)
{
if (mask & GS_PC_EXT_XMIT_DATA)
pc->ext_xmit_data = 0;
@@ -844,6 +875,482 @@ do_extcounters(Port * port, unsigned op, uint32_t unused, uint8_t * data)
return 0;
}
+static int do_portcounters_common(Port * port, unsigned op, uint32_t unused,
+ uint8_t * data,
+ pc_reset_function pc_reset_ptr,
+ pc_get_function pc_get_ptr,
+ pc_sum_function pc_sum_ptr)
+{
+ Node *node = port->node;
+ unsigned portnum;
+ Portcounters totals;
+ unsigned mask;
+ Port *p;
+ int i;
+
+ portnum = mad_get_field(data, 0, IB_PC_PORT_SELECT_F);
+ if (node->type != SWITCH_NODE && portnum != port->portnum)
+ return ERR_BAD_PARAM;
+
+ if (node->type == SWITCH_NODE && portnum > node->numports
+ && portnum != 0xff)
+ return ERR_BAD_PARAM;
+
+ DEBUG("in node %" PRIx64 " port %" PRIx64 " portnum %u",
+ node->nodeguid, port->portguid, portnum);
+
+ mask = mad_get_field(data, 0, IB_PC_COUNTER_SELECT_F);
+
+ if (portnum != 0xff) {
+ if (!(p = node_get_port(node, portnum)))
+ return ERR_BAD_PARAM;
+ if (op == IB_MAD_METHOD_SET)
+ pc_reset_ptr(&p->portcounters, mask);
+ pc_get_ptr(&p->portcounters, data);
+ return 0;
+ }
+
+ memset(&totals, 0, sizeof totals);
+
+ for (i = 0; i <= node->numports; i++) {
+ if (!(p = node_get_port(node, i)))
+ return ERR_BAD_PARAM;
+ if (op == IB_MAD_METHOD_SET)
+ pc_reset_ptr(&p->portcounters, mask);
+ pc_sum_ptr(&totals, &p->portcounters);
+ }
+
+ pc_get_ptr(&totals, data);
+ return 0;
+}
+
+static void pc_rcv_error_details_get(Portcounters * pc, uint8_t * data)
+{
+ mad_set_field(data, 0, IB_PC_RCV_LOCAL_PHY_ERR_F,
+ pc->rcv_error_details.PortLocalPhysicalErrors);
+ mad_set_field(data, 0, IB_PC_RCV_MALFORMED_PKT_ERR_F,
+ pc->rcv_error_details.PortMalformedPacketErrors);
+ mad_set_field(data, 0, IB_PC_RCV_BUF_OVR_ERR_F,
+ pc->rcv_error_details.PortBufferOverrunErrors);
+ mad_set_field(data, 0, IB_PC_RCV_DLID_MAP_ERR_F,
+ pc->rcv_error_details.PortDLIDMappingErrors);
+ mad_set_field(data, 0, IB_PC_RCV_VL_MAP_ERR_F,
+ pc->rcv_error_details.PortVLMappingErrors);
+ mad_set_field(data, 0, IB_PC_RCV_LOOPING_ERR_F,
+ pc->rcv_error_details.PortLoopingErrors);
+}
+
+static void pc_rcv_error_details_sum(Portcounters * totals, Portcounters * pc)
+{
+ totals->rcv_error_details.PortLocalPhysicalErrors =
+ addval(totals->rcv_error_details.PortLocalPhysicalErrors,
+ pc->rcv_error_details.PortLocalPhysicalErrors,
+ GS_PERF_LOCAL_PHYSICAL_ERRORS_LIMIT);
+ totals->rcv_error_details.PortMalformedPacketErrors =
+ addval(totals->rcv_error_details.PortMalformedPacketErrors,
+ pc->rcv_error_details.PortMalformedPacketErrors,
+ GS_PERF_MALFORMED_PACKET_ERRORS_LIMIT);
+ totals->rcv_error_details.PortBufferOverrunErrors =
+ addval(totals->rcv_error_details.PortBufferOverrunErrors,
+ pc->rcv_error_details.PortBufferOverrunErrors,
+ GS_PERF_BUFFER_OVERRUN_ERRORS_LIMIT);
+ totals->rcv_error_details.PortDLIDMappingErrors =
+ addval(totals->rcv_error_details.PortDLIDMappingErrors,
+ pc->rcv_error_details.PortDLIDMappingErrors,
+ GS_PERF_DLID_MAPPING_ERRORS_LIMIT);
+ totals->rcv_error_details.PortVLMappingErrors =
+ addval(totals->rcv_error_details.PortVLMappingErrors,
+ pc->rcv_error_details.PortVLMappingErrors,
+ GS_PERF_VL_MAPPING_ERRORS_LIMIT);
+ totals->rcv_error_details.PortLoopingErrors =
+ addval(totals->rcv_error_details.PortLoopingErrors,
+ pc->rcv_error_details.PortLoopingErrors,
+ GS_PERF_LOOPING_ERRORS_LIMIT);
+}
+
+static void pc_rcv_error_details_reset(Portcounters * pc, unsigned mask)
+{
+ if(mask & GS_PERF_LOCAL_PHYSICAL_ERRORS_MASK)
+ pc->rcv_error_details.PortLocalPhysicalErrors = 0;
+ if(mask & GS_PERF_MALFORMED_PACKET_ERRORS_MASK)
+ pc->rcv_error_details.PortMalformedPacketErrors = 0;
+ if(mask & GS_PERF_BUFFER_OVERRUN_ERRORS_MASK)
+ pc->rcv_error_details.PortBufferOverrunErrors = 0;
+ if(mask & GS_PERF_DLID_MAPPING_ERRORS_MASK)
+ pc->rcv_error_details.PortDLIDMappingErrors = 0;
+ if(mask & GS_PERF_VL_MAPPING_ERRORS_MASK)
+ pc->rcv_error_details.PortVLMappingErrors = 0;
+ if(mask & GS_PERF_LOOPING_ERRORS_MASK)
+ pc->rcv_error_details.PortLoopingErrors = 0;
+}
+
+static int do_rcv_error_details(Port * port, unsigned op, uint32_t unused, uint8_t * data)
+{
+ return do_portcounters_common(port, op, unused, data, pc_rcv_error_details_reset,
+ pc_rcv_error_details_get, pc_rcv_error_details_sum);
+}
+
+static void pc_xmit_discard_details_get(Portcounters * pc, uint8_t * data)
+{
+ mad_set_field(data, 0, IB_PC_XMT_INACT_DISC_F,
+ pc->xmit_discard_details.PortInactiveDiscards);
+ mad_set_field(data, 0, IB_PC_XMT_NEIGH_MTU_DISC_F,
+ pc->xmit_discard_details.PortNeighborMTUDiscards);
+ mad_set_field(data, 0, IB_PC_XMT_SW_LIFE_DISC_F,
+ pc->xmit_discard_details.PortSwLifetimeLimitDiscards);
+ mad_set_field(data, 0, IB_PC_XMT_SW_HOL_DISC_F,
+ pc->xmit_discard_details.PortSwHOQLifetimeLimitDiscards);
+}
+
+static void pc_xmit_discard_details_sum(Portcounters * totals, Portcounters * pc)
+{
+ totals->xmit_discard_details.PortInactiveDiscards =
+ addval(totals->xmit_discard_details.PortInactiveDiscards,
+ pc->xmit_discard_details.PortInactiveDiscards,
+ GS_PERF_INACTIVE_DISCARDS_LIMIT);
+ totals->xmit_discard_details.PortNeighborMTUDiscards =
+ addval(totals->xmit_discard_details.PortNeighborMTUDiscards,
+ pc->xmit_discard_details.PortNeighborMTUDiscards,
+ GS_PERF_NEIGHBOR_MTU_DISCARDS_LIMIT);
+ totals->xmit_discard_details.PortSwLifetimeLimitDiscards =
+ addval(totals->xmit_discard_details.PortSwLifetimeLimitDiscards,
+ pc->xmit_discard_details.PortSwLifetimeLimitDiscards,
+ GS_PERF_SW_LIFETIME_LIMIT_DISCARDS_LIMIT);
+ totals->xmit_discard_details.PortSwHOQLifetimeLimitDiscards =
+ addval(totals->xmit_discard_details.PortSwHOQLifetimeLimitDiscards,
+ pc->xmit_discard_details.PortSwHOQLifetimeLimitDiscards,
+ GS_PERF_SW_HOQ_LIFETIME_LIMIT_DISCARDS_LIMIT);
+}
+
+static void pc_xmit_discard_details_reset(Portcounters * pc, unsigned mask)
+{
+ if(mask & GS_PERF_INACTIVE_DISCARDS_MASK)
+ pc->xmit_discard_details.PortInactiveDiscards = 0;
+ if(mask & GS_PERF_NEIGHBOR_MTU_DISCARDS_MASK)
+ pc->xmit_discard_details.PortNeighborMTUDiscards = 0;
+ if(mask & GS_PERF_SW_LIFETIME_LIMIT_DISCARDS_MASK)
+ pc->xmit_discard_details.PortSwLifetimeLimitDiscards = 0;
+ if(mask & GS_PERF_SW_HOQ_LIFETIME_LIMIT_DISCARDS_MASK)
+ pc->xmit_discard_details.PortSwHOQLifetimeLimitDiscards = 0;
+}
+
+static int do_xmit_discard_details(Port * port, unsigned op, uint32_t unused, uint8_t * data)
+{
+ return do_portcounters_common(port, op, unused, data, pc_xmit_discard_details_reset,
+ pc_xmit_discard_details_get, pc_xmit_discard_details_sum);
+}
+
+static void pc_op_rcv_counters_get(Portcounters * pc, uint8_t * data)
+{
+ mad_set_field(data, 0, IB_PC_PORT_OP_RCV_PKTS_F,
+ pc->op_rcv_counters.PortOpRcvPkts);
+ mad_set_field(data, 0, IB_PC_PORT_OP_RCV_DATA_F,
+ pc->op_rcv_counters.PortOpRcvData);
+}
+
+static void pc_op_rcv_counters_sum(Portcounters * totals, Portcounters * pc)
+{
+ totals->op_rcv_counters.PortOpRcvPkts =
+ addval(totals->op_rcv_counters.PortOpRcvPkts,
+ pc->op_rcv_counters.PortOpRcvPkts, GS_PERF_OP_RCV_PKTS_LIMIT);
+ totals->op_rcv_counters.PortOpRcvData =
+ addval(totals->op_rcv_counters.PortOpRcvData,
+ pc->op_rcv_counters.PortOpRcvData, GS_PERF_OP_RCV_DATA_LIMIT);
+}
+
+static void pc_op_rcv_counters_reset(Portcounters * pc, unsigned mask)
+{
+ if(mask & GS_PERF_OP_RCV_PKTS_MASK)
+ pc->op_rcv_counters.PortOpRcvPkts = 0;
+ if(mask & GS_PERF_OP_RCV_DATA_MASK)
+ pc->op_rcv_counters.PortOpRcvData = 0;
+}
+
+static int do_op_rcv_counters(Port * port, unsigned op, uint32_t unused, uint8_t * data)
+{
+ return do_portcounters_common(port, op, unused, data, pc_op_rcv_counters_reset,
+ pc_op_rcv_counters_get, pc_op_rcv_counters_sum);
+}
+
+static void pc_flow_ctl_counters_get(Portcounters * pc, uint8_t * data)
+{
+ mad_set_field(data, 0, IB_PC_PORT_XMIT_FLOW_PKTS_F,
+ pc->flow_ctl_counters.PortXmitFlowPkts);
+ mad_set_field(data, 0, IB_PC_PORT_RCV_FLOW_PKTS_F,
+ pc->flow_ctl_counters.PortRcvFlowPkts);
+}
+
+static void pc_flow_ctl_counters_sum(Portcounters * totals, Portcounters * pc)
+{
+ totals->flow_ctl_counters.PortXmitFlowPkts =
+ addval(totals->flow_ctl_counters.PortXmitFlowPkts,
+ pc->flow_ctl_counters.PortXmitFlowPkts,
+ GS_PERF_XMIT_FLOW_PKTS_LIMIT);
+ totals->flow_ctl_counters.PortRcvFlowPkts =
+ addval(totals->flow_ctl_counters.PortRcvFlowPkts,
+ pc->flow_ctl_counters.PortRcvFlowPkts,
+ GS_PERF_RCV_FLOW_PKTS_LIMIT);
+}
+
+static void pc_flow_ctl_counters_reset(Portcounters * pc, unsigned mask)
+{
+ if(mask & GS_PERF_XMIT_FLOW_PKTS_MASK)
+ pc->flow_ctl_counters.PortXmitFlowPkts = 0;
+ if(mask & GS_PERF_RCV_FLOW_PKTS_MASK)
+ pc->flow_ctl_counters.PortRcvFlowPkts = 0;
+}
+
+static int do_flow_ctl_counters(Port * port, unsigned op, uint32_t unused, uint8_t * data)
+{
+ return do_portcounters_common(port, op, unused, data, pc_flow_ctl_counters_reset,
+ pc_flow_ctl_counters_get, pc_flow_ctl_counters_sum);
+}
+
+static void pc_vl_op_packets_get(Portcounters * pc, uint8_t * data)
+{
+ mad_set_field(data, 0, IB_PC_PORT_VL_OP_PACKETS0_F,
+ pc->vl_op_packets.PortVLOpPackets[0]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_OP_PACKETS1_F,
+ pc->vl_op_packets.PortVLOpPackets[1]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_OP_PACKETS2_F,
+ pc->vl_op_packets.PortVLOpPackets[2]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_OP_PACKETS3_F,
+ pc->vl_op_packets.PortVLOpPackets[3]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_OP_PACKETS4_F,
+ pc->vl_op_packets.PortVLOpPackets[4]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_OP_PACKETS5_F,
+ pc->vl_op_packets.PortVLOpPackets[5]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_OP_PACKETS6_F,
+ pc->vl_op_packets.PortVLOpPackets[6]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_OP_PACKETS7_F,
+ pc->vl_op_packets.PortVLOpPackets[7]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_OP_PACKETS8_F,
+ pc->vl_op_packets.PortVLOpPackets[8]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_OP_PACKETS9_F,
+ pc->vl_op_packets.PortVLOpPackets[9]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_OP_PACKETS10_F,
+ pc->vl_op_packets.PortVLOpPackets[10]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_OP_PACKETS11_F,
+ pc->vl_op_packets.PortVLOpPackets[11]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_OP_PACKETS12_F,
+ pc->vl_op_packets.PortVLOpPackets[12]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_OP_PACKETS13_F,
+ pc->vl_op_packets.PortVLOpPackets[13]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_OP_PACKETS14_F,
+ pc->vl_op_packets.PortVLOpPackets[14]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_OP_PACKETS15_F,
+ pc->vl_op_packets.PortVLOpPackets[15]);
+}
+
+static void pc_vl_op_packets_sum(Portcounters * totals, Portcounters * pc)
+{
+ int i;
+ for(i = 0; i < 16; i++)
+ totals->vl_op_packets.PortVLOpPackets[i] =
+ addval(totals->vl_op_packets.PortVLOpPackets[i],
+ pc->vl_op_packets.PortVLOpPackets[i],
+ GS_PERF_VL_OP_PACKETS_LIMIT);
+}
+
+static void pc_vl_op_packets_reset(Portcounters * pc, unsigned mask)
+{
+ int i;
+ for(i = 0; i < 16; i++)
+ if(mask & (1UL << i))
+ pc->vl_op_packets.PortVLOpPackets[i] = 0;
+}
+
+static int do_vl_op_packets(Port * port, unsigned op, uint32_t unused, uint8_t * data)
+{
+ return do_portcounters_common(port, op, unused, data, pc_vl_op_packets_reset,
+ pc_vl_op_packets_get, pc_vl_op_packets_sum);
+}
+
+static void pc_vl_op_data_get(Portcounters * pc, uint8_t * data)
+{
+ mad_set_field(data, 0, IB_PC_PORT_VL_OP_DATA0_F,
+ pc->vl_op_data.PortVLOpData[0]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_OP_DATA1_F,
+ pc->vl_op_data.PortVLOpData[1]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_OP_DATA2_F,
+ pc->vl_op_data.PortVLOpData[2]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_OP_DATA3_F,
+ pc->vl_op_data.PortVLOpData[3]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_OP_DATA4_F,
+ pc->vl_op_data.PortVLOpData[4]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_OP_DATA5_F,
+ pc->vl_op_data.PortVLOpData[5]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_OP_DATA6_F,
+ pc->vl_op_data.PortVLOpData[6]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_OP_DATA7_F,
+ pc->vl_op_data.PortVLOpData[7]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_OP_DATA8_F,
+ pc->vl_op_data.PortVLOpData[8]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_OP_DATA9_F,
+ pc->vl_op_data.PortVLOpData[9]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_OP_DATA10_F,
+ pc->vl_op_data.PortVLOpData[10]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_OP_DATA11_F,
+ pc->vl_op_data.PortVLOpData[11]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_OP_DATA12_F,
+ pc->vl_op_data.PortVLOpData[12]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_OP_DATA13_F,
+ pc->vl_op_data.PortVLOpData[13]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_OP_DATA14_F,
+ pc->vl_op_data.PortVLOpData[14]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_OP_DATA15_F,
+ pc->vl_op_data.PortVLOpData[15]);
+}
+
+static void pc_vl_op_data_sum(Portcounters * totals, Portcounters * pc)
+{
+ int i;
+ for(i = 0; i < 16; i++)
+ totals->vl_op_data.PortVLOpData[i] =
+ addval(totals->vl_op_data.PortVLOpData[i],
+ pc->vl_op_data.PortVLOpData[i], GS_PERF_VL_OP_DATA_LIMIT);
+}
+
+static void pc_vl_op_data_reset(Portcounters * pc, unsigned mask)
+{
+ int i;
+ for(i = 0; i < 16; i++)
+ {
+ if(mask & (1UL << i))
+ pc->vl_op_data.PortVLOpData[i] = 0;
+ }
+}
+
+static int do_vl_op_data(Port * port, unsigned op, uint32_t unused, uint8_t * data)
+{
+ return do_portcounters_common(port, op, unused, data, pc_vl_op_data_reset,
+ pc_vl_op_data_get, pc_vl_op_data_sum);
+}
+
+static void pc_vl_xmit_flow_ctl_update_errors_get(Portcounters * pc, uint8_t * data)
+{
+ mad_set_field(data, 0, IB_PC_PORT_VL_XMIT_FLOW_CTL_UPDATE_ERRORS0_F,
+ pc->vl_xmit_flow_ctl_update_errors.PortVLXmitFlowCtlUpdateErrors[0]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_XMIT_FLOW_CTL_UPDATE_ERRORS1_F,
+ pc->vl_xmit_flow_ctl_update_errors.PortVLXmitFlowCtlUpdateErrors[1]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_XMIT_FLOW_CTL_UPDATE_ERRORS2_F,
+ pc->vl_xmit_flow_ctl_update_errors.PortVLXmitFlowCtlUpdateErrors[2]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_XMIT_FLOW_CTL_UPDATE_ERRORS3_F,
+ pc->vl_xmit_flow_ctl_update_errors.PortVLXmitFlowCtlUpdateErrors[3]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_XMIT_FLOW_CTL_UPDATE_ERRORS4_F,
+ pc->vl_xmit_flow_ctl_update_errors.PortVLXmitFlowCtlUpdateErrors[4]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_XMIT_FLOW_CTL_UPDATE_ERRORS5_F,
+ pc->vl_xmit_flow_ctl_update_errors.PortVLXmitFlowCtlUpdateErrors[5]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_XMIT_FLOW_CTL_UPDATE_ERRORS6_F,
+ pc->vl_xmit_flow_ctl_update_errors.PortVLXmitFlowCtlUpdateErrors[6]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_XMIT_FLOW_CTL_UPDATE_ERRORS7_F,
+ pc->vl_xmit_flow_ctl_update_errors.PortVLXmitFlowCtlUpdateErrors[7]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_XMIT_FLOW_CTL_UPDATE_ERRORS8_F,
+ pc->vl_xmit_flow_ctl_update_errors.PortVLXmitFlowCtlUpdateErrors[8]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_XMIT_FLOW_CTL_UPDATE_ERRORS9_F,
+ pc->vl_xmit_flow_ctl_update_errors.PortVLXmitFlowCtlUpdateErrors[9]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_XMIT_FLOW_CTL_UPDATE_ERRORS10_F,
+ pc->vl_xmit_flow_ctl_update_errors.PortVLXmitFlowCtlUpdateErrors[10]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_XMIT_FLOW_CTL_UPDATE_ERRORS11_F,
+ pc->vl_xmit_flow_ctl_update_errors.PortVLXmitFlowCtlUpdateErrors[11]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_XMIT_FLOW_CTL_UPDATE_ERRORS12_F,
+ pc->vl_xmit_flow_ctl_update_errors.PortVLXmitFlowCtlUpdateErrors[12]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_XMIT_FLOW_CTL_UPDATE_ERRORS13_F,
+ pc->vl_xmit_flow_ctl_update_errors.PortVLXmitFlowCtlUpdateErrors[13]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_XMIT_FLOW_CTL_UPDATE_ERRORS14_F,
+ pc->vl_xmit_flow_ctl_update_errors.PortVLXmitFlowCtlUpdateErrors[14]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_XMIT_FLOW_CTL_UPDATE_ERRORS15_F,
+ pc->vl_xmit_flow_ctl_update_errors.PortVLXmitFlowCtlUpdateErrors[15]);
+}
+
+static void pc_vl_xmit_flow_ctl_update_errors_sum(Portcounters * totals, Portcounters * pc)
+{
+ int i;
+ for(i = 0; i < 16; i++)
+ totals->vl_xmit_flow_ctl_update_errors.PortVLXmitFlowCtlUpdateErrors[i] =
+ addval(totals->vl_xmit_flow_ctl_update_errors.PortVLXmitFlowCtlUpdateErrors[i],
+ pc->vl_xmit_flow_ctl_update_errors.PortVLXmitFlowCtlUpdateErrors[i],
+ GS_PERF_VL_XMIT_FLOW_CTL_UPDATE_ERRORS);
+}
+
+static void pc_vl_xmit_flow_ctl_update_errors_reset(Portcounters * pc, unsigned mask)
+{
+ int i;
+ for(i = 0; i < 16; i++)
+ if(mask & (1UL << i))
+ pc->vl_xmit_flow_ctl_update_errors.PortVLXmitFlowCtlUpdateErrors[i] = 0;
+}
+
+static int do_vl_xmit_flow_ctl_update_errors(Port * port, unsigned op, uint32_t unused, uint8_t * data)
+{
+ return do_portcounters_common(port, op, unused, data, pc_vl_xmit_flow_ctl_update_errors_reset,
+ pc_vl_xmit_flow_ctl_update_errors_get, pc_vl_xmit_flow_ctl_update_errors_sum);
+}
+
+static void pc_vl_xmit_wait_counters_get(Portcounters * pc, uint8_t * data)
+{
+ mad_set_field(data, 0, IB_PC_PORT_VL_XMIT_WAIT0_F,
+ pc->vl_xmit_wait_counters.PortVLXmitWait[0]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_XMIT_WAIT1_F,
+ pc->vl_xmit_wait_counters.PortVLXmitWait[1]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_XMIT_WAIT2_F,
+ pc->vl_xmit_wait_counters.PortVLXmitWait[2]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_XMIT_WAIT3_F,
+ pc->vl_xmit_wait_counters.PortVLXmitWait[3]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_XMIT_WAIT4_F,
+ pc->vl_xmit_wait_counters.PortVLXmitWait[4]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_XMIT_WAIT5_F,
+ pc->vl_xmit_wait_counters.PortVLXmitWait[5]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_XMIT_WAIT6_F,
+ pc->vl_xmit_wait_counters.PortVLXmitWait[6]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_XMIT_WAIT7_F,
+ pc->vl_xmit_wait_counters.PortVLXmitWait[7]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_XMIT_WAIT8_F,
+ pc->vl_xmit_wait_counters.PortVLXmitWait[8]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_XMIT_WAIT9_F,
+ pc->vl_xmit_wait_counters.PortVLXmitWait[9]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_XMIT_WAIT10_F,
+ pc->vl_xmit_wait_counters.PortVLXmitWait[10]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_XMIT_WAIT11_F,
+ pc->vl_xmit_wait_counters.PortVLXmitWait[11]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_XMIT_WAIT12_F,
+ pc->vl_xmit_wait_counters.PortVLXmitWait[12]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_XMIT_WAIT13_F,
+ pc->vl_xmit_wait_counters.PortVLXmitWait[13]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_XMIT_WAIT14_F,
+ pc->vl_xmit_wait_counters.PortVLXmitWait[14]);
+ mad_set_field(data, 0, IB_PC_PORT_VL_XMIT_WAIT15_F,
+ pc->vl_xmit_wait_counters.PortVLXmitWait[15]);
+}
+
+static void pc_vl_xmit_wait_counters_sum(Portcounters * totals, Portcounters * pc)
+{
+ int i;
+ for(i = 0; i < 16; i++)
+ totals->vl_xmit_wait_counters.PortVLXmitWait[i] =
+ addval(totals->vl_xmit_wait_counters.PortVLXmitWait[i],
+ pc->vl_xmit_wait_counters.PortVLXmitWait[i],
+ GS_PERF_VL_XMIT_WAIT_COUNTERS_LIMIT);
+}
+
+static void pc_vl_xmit_wait_counters_reset(Portcounters * pc, unsigned mask)
+{
+ int i;
+ for(i = 0; i < 16; i++)
+ if(mask & (1UL << i))
+ pc->vl_xmit_wait_counters.PortVLXmitWait[i] = 0;
+}
+
+static int do_vl_xmit_wait_counters(Port * port, unsigned op, uint32_t unused,
+ uint8_t * data)
+{
+ return do_portcounters_common(port, op, unused, data,
+ pc_vl_xmit_wait_counters_reset,
+ pc_vl_xmit_wait_counters_get,
+ pc_vl_xmit_wait_counters_sum);
+}
+
+
static char *pathstr(int lid, ib_dr_path_t * path)
{
static char buf[1024] = "local";
@@ -851,7 +1358,7 @@ static char *pathstr(int lid, ib_dr_path_t * path)
int i;
if (0 && lid != -1) {
- sprintf(buf, "lid 0x%x", lid);
+ sprintf(buf, "lid %u", lid);
return buf;
}
for (i = 0; i < path->cnt + 1; i++) {
@@ -870,12 +1377,12 @@ static int switch_lookup(Node * node, int lid)
{
int outport;
- DEBUG("node 0x%" PRIx64 " lid %d", node->nodeguid, lid);
+ DEBUG("node 0x%" PRIx64 " lid %u", node->nodeguid, lid);
if (!node->sw)
return -1;
if (lid > node->sw->linearFDBtop || (outport = node->sw->fdb[lid]) < 0) {
- IBWARN("sw guid %" PRIx64 ": bad lid %d", node->nodeguid, lid);
+ IBWARN("sw guid %" PRIx64 ": bad lid %u", node->nodeguid, lid);
return -1;
}
@@ -895,7 +1402,7 @@ static int port_get_remote(Port * port, Node ** remotenode, Port ** remoteport)
static int is_port_lid(Port * port, int lid)
{
- DEBUG("port 0x%" PRIx64 " lid %d lmc %d target lid %d",
+ DEBUG("port 0x%" PRIx64 " lid %u lmc %d target lid %u",
port->portguid, port->lid, port->lmc, lid);
if (lid < port->lid || lid > port->lid + (1 << port->lmc) - 1)
return 0;
@@ -929,7 +1436,7 @@ static Port *lid_route_MAD(Port * port, int lid)
Node *node = port->node;
Port *tport = port;
- DEBUG("Node %" PRIx64 " port %" PRIx64 " (%d) lid %d",
+ DEBUG("Node %" PRIx64 " port %" PRIx64 " (%d) lid %u",
node->nodeguid, port->portguid, port->portnum, lid);
if (lid == 0) {
@@ -955,7 +1462,7 @@ static Port *lid_route_MAD(Port * port, int lid)
if (portnum < 0 || portnum > node->numports) {
pc_add_error_rcvswitchrelay(port);
- DEBUG("illegal lid %d (outport %d node %s ports %d)",
+ DEBUG("illegal lid %u (outport %d node %s ports %d)",
lid, portnum, node->nodeid, node->numports);
return 0;
}
@@ -1108,9 +1615,7 @@ static Port *route_MAD(Port * port, int response, int lid, ib_dr_path_t * path)
direct_route_out_MAD(port, path);
}
-int modified;
-
-Smpfn *get_handle_fn(ib_rpc_t rpc, int response)
+static Smpfn *get_handle_fn(ib_rpc_t rpc, int response)
{
Smpfn *fn;
@@ -1120,14 +1625,14 @@ Smpfn *get_handle_fn(ib_rpc_t rpc, int response)
if (rpc.mgtclass == IB_SMI_CLASS || rpc.mgtclass == IB_SMI_DIRECT_CLASS) {
if (rpc.attr.id >= IB_ATTR_LAST
|| !(fn = attrs[rpc.mgtclass & 0xf][rpc.attr.id]))
- return 0; // not supported attribute ???
+ return 0; // attribute/method not supported ???
return fn;
}
if (rpc.mgtclass == IB_PERFORMANCE_CLASS) {
if (rpc.attr.id >= IB_GSI_ATTR_LAST
|| !(fn = attrs[rpc.mgtclass & 0xf][rpc.attr.id]))
- return 0; // not supported attribute ???
+ return 0; // attribute/method not supported ???
return fn;
}
@@ -1161,13 +1666,13 @@ int process_packet(Client * cl, void *p, int size, Client ** dcl)
return -1;
if (rpc.method == 0x7) {
- IBWARN("got trap repress - drop");
+ IBWARN("lid %u got trap repress - dropping", ntohs(r->dlid));
*dcl = 0;
return 0;
}
if (!(port = route_MAD(cl->port, response, ntohs(r->dlid), &path))) {
- IBWARN("routing failed: no route to dest lid %d path %s",
+ IBWARN("routing failed: no route to dest lid %u path %s",
ntohs(r->dlid), pathstr(0, &path));
goto _dropped;
}
@@ -1198,9 +1703,6 @@ int process_packet(Client * cl, void *p, int size, Client ** dcl)
if ((status = fn(port, rpc.method, rpc.attr.mod, data)) < 0)
goto _dropped;
- if (rpc.method == 2)
- modified++;
-
reply_MAD(r->mad, &rpc, &path, status, data);
tlid = r->dlid;
@@ -1231,7 +1733,7 @@ static int encode_trap128(Port * port, char *data)
if (port->node->type != SWITCH_NODE)
return -1;
if (!port->lid || !port->smlid) {
- VERB("switch trap 128 for lid %d with smlid %d",
+ VERB("switch trap 128 for lid %u with smlid %u",
port->lid, port->smlid);
return -1;
}
@@ -1251,7 +1753,7 @@ static int encode_trap128(Port * port, char *data)
static int encode_trap144(Port * port, char *data)
{
if (!port->lid || !port->smlid) {
- VERB("switch trap 144 for lid %d with smlid %d",
+ VERB("switch trap 144 for lid %u with smlid %u",
port->lid, port->smlid);
return -1;
}
@@ -1281,27 +1783,28 @@ static int encode_trap_header(char *buf)
return 0;
}
-int send_trap(Port * port, int trapnum)
+int send_trap(Port * port, unsigned trapnum)
{
struct sim_request req;
Client *cl;
int ret, lid = port->lid;
char *data = req.mad + 64; /* data offset */
- EncodeTrapfn *encode_trapfn = encodetrap[trapnum];
+ EncodeTrapfn *encode_trapfn;
Port *destport;
- if (!encode_trapfn) {
+ if (trapnum >= TRAP_NUM_LAST) {
IBWARN("trap number %d not supported", trapnum);
return -1;
}
+ encode_trapfn = encodetrap[trapnum];
memset(req.mad, 0, sizeof(req.mad));
encode_trap_header(req.mad);
if (encode_trapfn(port, data) < 0)
return -1;
if (!(destport = lid_route_MAD(port, port->smlid))) {
- IBWARN("routing failed: no route to dest lid %d", port->smlid);
+ IBWARN("routing failed: no route to dest lid %u", port->smlid);
return -1;
}
diff --git a/ibsim/sim_net.c b/ibsim/sim_net.c
index ee268e0..10820ba 100644
--- a/ibsim/sim_net.c
+++ b/ibsim/sim_net.c
@@ -67,7 +67,7 @@ Port *default_port;
static const uint8_t smaport[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFE, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x02, 0x48,
+ 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48,
0x00, 0x00, 0x0F, 0xF9, 0x00, 0x03, 0x03, 0x01,
0x14, 0x52, 0x00, 0x11, 0x10, 0x40, 0x00, 0x08,
0x08, 0x03, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,
@@ -80,7 +80,7 @@ static const uint8_t swport[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x02,
- 0x14, 0x52, 0x00, 0x11, 0x40, 0x40, 0x00, 0x08,
+ 0x12, 0x52, 0x00, 0x11, 0x40, 0x40, 0x00, 0x08,
0x08, 0x04, 0xFF, 0x10, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -100,9 +100,9 @@ static const uint8_t swport_down[] = {
static const uint8_t hcaport[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFE, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x02, 0x00, 0x01, 0x00, 0x50, 0x02, 0x48,
+ 0x00, 0x02, 0x00, 0x01, 0x00, 0x50, 0x00, 0x48,
0x00, 0x00, 0x0F, 0xF9, 0x01, 0x03, 0x03, 0x02,
- 0x14, 0x52, 0x00, 0x11, 0x40, 0x40, 0x00, 0x08,
+ 0x12, 0x52, 0x00, 0x11, 0x40, 0x40, 0x00, 0x08,
0x08, 0x04, 0xFF, 0x10, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x20, 0x1F, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -111,7 +111,7 @@ static const uint8_t hcaport[] = {
static const uint8_t hcaport_down[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFE, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x02, 0x00, 0x01, 0x00, 0x10, 0x02, 0x48,
+ 0x00, 0x02, 0x00, 0x01, 0x00, 0x10, 0x00, 0x48,
0x00, 0x00, 0x0F, 0xF9, 0x01, 0x03, 0x03, 0x01,
0x11, 0x22, 0x00, 0x11, 0x40, 0x40, 0x00, 0x08,
0x08, 0x04, 0xE9, 0x10, 0x00, 0x00, 0x00, 0x00,
@@ -322,6 +322,8 @@ static Node *new_node(int type, char *nodename, char *nodedesc, int nodeports)
guids[type]++; // reserve single guid;
} else {
memcpy(nd->nodeinfo, hcanodeinfo, sizeof(nd->nodeinfo));
+ if (type == ROUTER_NODE)
+ mad_set_field(nd->nodeinfo, 0, IB_NODE_TYPE_F, ROUTER_NODE);
guids[type] += nodeports + 1; // reserve guids;
}
@@ -403,7 +405,7 @@ static int is_linkwidth_valid(int width)
static int is_linkspeed_valid(int speed)
{
- /* speed is 2.5G, 5.0G, or 10.0 G */
+ /* speed is 2.5G, 5.0G, or 10.0G */
if (speed < 1 || speed > 7) {
IBWARN("bad speed %d - should be between 1 to 7", speed);
return 0;
@@ -677,7 +679,6 @@ static int parse_port(char *line, Node * node, int type, int maxports)
IBWARN("bad port option");
return -1;
}
- line = s + 1;
}
if (type != SWITCH_NODE && line && parse_port_lid_and_lmc(port, line) < 0) {
IBWARN("cannot parse lid, lmc");
@@ -1114,7 +1115,7 @@ int link_ports(Port * lport, Port * rport)
rport->remoteport = lport->portnum;
set_portinfo(rport, rnode->type == SWITCH_NODE ? swport : hcaport);
memcpy(rport->remotenodeid, lnode->nodeid, sizeof(rport->remotenodeid));
- lport->state = rport->state = 2; // Initialilze
+ lport->state = rport->state = 2; // Initialize
lport->physstate = rport->physstate = 5; // LinkUP
if (lnode->sw)
lnode->sw->portchange = 1;
diff --git a/tests/Makefile b/tests/Makefile
index dd4cd55..a48cfc4 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -1,4 +1,4 @@
-progs:= mcast_storm
+progs:= subnet_discover query_many mcast_storm
-include ../defs.mk
diff --git a/tests/mcast_storm.c b/tests/mcast_storm.c
index b2bf19a..61f0348 100644
--- a/tests/mcast_storm.c
+++ b/tests/mcast_storm.c
@@ -29,6 +29,7 @@
#define TMO 100
#define DEFAULT_PREFIX 0xfe80000000000000ULL
+#define DEFAULT_MGID_PREFIX 0xff00000000000000ULL
/* Multicast Member Record Component Masks */
#define IB_MCR_COMPMASK_MGID (1ULL<<0)
@@ -57,39 +58,97 @@ struct addr_data {
ib_portid_t dport;
};
+struct mcmember_params {
+ uint32_t qkey;
+ uint16_t mlid;
+ uint8_t mtu;
+ int tclass;
+ uint16_t pkey;
+ uint8_t rate;
+ int sl;
+ int flow_label;
+ int hop_limit;
+ uint8_t scope;
+ uint8_t join_state;
+ int proxy_join;
+};
+
+static const struct mcmember_params null_params = {
+ .tclass = -1,
+ .sl = -1,
+ .flow_label = -1,
+ .hop_limit = -1,
+ .proxy_join = -1,
+};
+
+static const struct mcmember_params mcmember_params_join = {
+ .tclass = -1,
+ .sl = -1,
+ .flow_label = -1,
+ .hop_limit = -1,
+ .join_state = 1,
+ .proxy_join = -1,
+};
+
+static const struct mcmember_params mcmember_params_create = {
+ .qkey = 0x80010000,
+ .mtu = 4,
+ .tclass = 0,
+ .pkey = 0xffff,
+ .rate = 3,
+ .sl = 0,
+ .flow_label = 0,
+ .hop_limit = -1,
+ .join_state = 1,
+ .proxy_join = -1,
+};
+
static ibmad_gid_t mgid_ipoib = {
0xff, 0x12, 0x40, 0x1b, 0xff, 0xff, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff
};
-uint64_t build_mcm_rec(uint8_t * data, ibmad_gid_t mgid, ibmad_gid_t port_gid,
- uint8_t join_state)
+static int64_t add_rid(uint8_t *data, ibmad_gid_t mgid, ibmad_gid_t port_gid)
{
- memset(data, 0, IB_SA_DATA_SIZE);
mad_set_array(data, 0, IB_SA_MCM_MGID_F, mgid);
mad_set_array(data, 0, IB_SA_MCM_PORTGID_F, port_gid);
- mad_set_field(data, 0, IB_SA_MCM_JOIN_STATE_F, join_state);
- return IB_MCR_COMPMASK_MGID | IB_MCR_COMPMASK_PORT_GID |
- IB_MCR_COMPMASK_JOIN_STATE;
+ return IB_MCR_COMPMASK_MGID | IB_MCR_COMPMASK_PORT_GID;
}
-uint64_t build_mcm_create_rec(uint8_t * data, ibmad_gid_t mgid,
- ibmad_gid_t port_gid, uint8_t join_state)
+static uint64_t build_mcm_rec(uint8_t * data, const struct mcmember_params *p)
{
- uint64_t comp_mask = build_mcm_rec(data, mgid, port_gid, join_state);
-
- mad_set_field(data, 0, IB_SA_MCM_QKEY_F, 0x80010000);
- mad_set_field(data, 0, IB_SA_MCM_SL_F, 0);
- mad_set_field(data, 0, IB_SA_MCM_MTU_F, 4);
- mad_set_field(data, 0, IB_SA_MCM_RATE_F, 3);
- mad_set_field(data, 0, IB_SA_MCM_TCLASS_F, 0);
- mad_set_field(data, 0, IB_SA_MCM_PKEY_F, 0xffff);
- mad_set_field(data, 0, IB_SA_MCM_FLOW_LABEL_F, 0);
-
- return comp_mask | IB_MCR_COMPMASK_QKEY | IB_MCR_COMPMASK_SL |
- IB_MCR_COMPMASK_MTU | IB_MCR_COMPMASK_RATE | IB_MCR_COMPMASK_PKEY |
- IB_MCR_COMPMASK_TCLASS | IB_MCR_COMPMASK_FLOW;
+#define SET_FIELD1(val, mask, field) \
+ if (val) { \
+ mad_set_field(data, 0, field, val); \
+ comp_mask |= mask; \
+ }
+
+#define SET_FIELD(obj, name, mask, field) \
+ if (obj->name != null_params.name) { \
+ mad_set_field(data, 0, field, obj->name); \
+ comp_mask |= mask; \
+ }
+
+ uint64_t comp_mask = 0;
+
+ memset(data, 0, IB_SA_DATA_SIZE);
+
+ if (!p)
+ return comp_mask;
+
+ SET_FIELD(p, qkey, IB_MCR_COMPMASK_QKEY, IB_SA_MCM_QKEY_F);
+ SET_FIELD(p, mlid, IB_MCR_COMPMASK_MLID, IB_SA_MCM_MLID_F);
+ SET_FIELD(p, mtu, IB_MCR_COMPMASK_MTU, IB_SA_MCM_MTU_F);
+ SET_FIELD(p, tclass, IB_MCR_COMPMASK_TCLASS, IB_SA_MCM_TCLASS_F);
+ SET_FIELD(p, pkey, IB_MCR_COMPMASK_PKEY, IB_SA_MCM_PKEY_F);
+ SET_FIELD(p, rate, IB_MCR_COMPMASK_RATE, IB_SA_MCM_RATE_F);
+ SET_FIELD(p, sl, IB_MCR_COMPMASK_SL, IB_SA_MCM_SL_F);
+ SET_FIELD(p, flow_label, IB_MCR_COMPMASK_FLOW, IB_SA_MCM_FLOW_LABEL_F);
+ SET_FIELD(p, join_state, IB_MCR_COMPMASK_JOIN_STATE, IB_SA_MCM_JOIN_STATE_F);
+ SET_FIELD(p, proxy_join, IB_MCR_COMPMASK_PROXY, IB_SA_MCM_PROXY_JOIN_F);
+
+ return comp_mask;
}
static void build_mcm_rec_umad(void *umad, ib_portid_t * dport, int method,
@@ -155,46 +214,29 @@ static int recv_res(struct addr_data *a, uint8_t * umad, int length)
return 1;
}
-static int send_create(struct addr_data *a, uint8_t * umad, int len,
- ibmad_gid_t mgid, ibmad_gid_t port_gid)
-{
- uint8_t data[IB_SA_DATA_SIZE];
- uint64_t comp_mask;
-
- comp_mask = build_mcm_create_rec(data, mgid, port_gid, 1);
-
- return send_req(a, umad, len, IB_MAD_METHOD_SET, comp_mask, data);
-}
-
static int send_join(struct addr_data *a, uint8_t * umad, int len,
- ibmad_gid_t mgid, ibmad_gid_t port_gid)
+ ibmad_gid_t mgid, ibmad_gid_t port_gid,
+ uint64_t comp_mask, uint8_t data[])
{
- uint8_t data[IB_SA_DATA_SIZE];
- uint64_t comp_mask;
-
- comp_mask = build_mcm_rec(data, mgid, port_gid, 1);
+ comp_mask |= add_rid(data, mgid, port_gid);
return send_req(a, umad, len, IB_MAD_METHOD_SET, comp_mask, data);
}
static int send_leave(struct addr_data *a, uint8_t * umad, int len,
- ibmad_gid_t mgid, ibmad_gid_t port_gid)
+ ibmad_gid_t mgid, ibmad_gid_t port_gid,
+ uint64_t comp_mask, uint8_t data[])
{
- uint8_t data[IB_SA_DATA_SIZE];
- uint64_t comp_mask;
-
- comp_mask = build_mcm_rec(data, mgid, port_gid, 1);
+ comp_mask |= add_rid(data, mgid, port_gid);
return send_req(a, umad, len, IB_MAD_METHOD_DELETE, comp_mask, data);
}
static int send_query(struct addr_data *a, uint8_t * umad, int len,
- ibmad_gid_t mgid, ibmad_gid_t port_gid)
+ ibmad_gid_t mgid, ibmad_gid_t port_gid,
+ uint64_t comp_mask, uint8_t data[])
{
- uint8_t data[IB_SA_DATA_SIZE];
- uint64_t comp_mask;
-
- comp_mask = build_mcm_rec(data, mgid, port_gid, 1);
+ comp_mask |= add_rid(data, mgid, port_gid);
return send_req(a, umad, len, IB_MAD_METHOD_GET, comp_mask, data);
}
@@ -221,8 +263,7 @@ static int recv_all(struct addr_data *a, void *umad, int len)
method = mad_get_field(mad, 0, IB_MAD_METHOD_F);
status = mad_get_field(mad, 0, IB_MAD_STATUS_F);
- if (status &&
- (method & 0x7f) == (IB_MAD_METHOD_GET_RESPONSE & 0x7f)) {
+ if (status) {
trid = mad_get_field64(mad, 0, IB_MAD_TRID_F);
info("mad trid 0x%016" PRIx64
": method = %x status = %x.\n",
@@ -236,60 +277,32 @@ static int recv_all(struct addr_data *a, void *umad, int len)
}
static int rereg_port(struct addr_data *a, uint8_t * umad, int len,
- ibmad_gid_t mgid, struct gid_list *list)
+ ibmad_gid_t mgid, struct gid_list *list,
+ uint64_t comp_mask, uint8_t data[])
{
- if (send_leave(a, umad, len, mgid, list->gid))
+ if (send_leave(a, umad, len, mgid, list->gid, comp_mask, data))
return -1;
- if (send_join(a, umad, len, mgid, list->gid))
+ if (send_join(a, umad, len, mgid, list->gid, comp_mask, data))
return -1;
- list->trid = mad_get_field64(umad_get_mad(umad), 0, IB_MAD_TRID_F);
-
- return 0;
-}
-static int rereg_send_all(struct addr_data *a, ibmad_gid_t mgid,
- struct gid_list *list, unsigned cnt)
-{
- uint8_t *umad;
- int len = 256;
- int i;
-
- info("%s:... cnt = %u\n", __func__, cnt);
-
- umad = calloc(1, len + umad_size());
- if (!umad) {
- err("cannot alloc mem for umad: %s\n", strerror(errno));
- return -1;
- }
-
- for (i = 0; i < cnt; i++)
- rereg_port(a, umad, len, mgid, &list[i]);
-
- info("%s: sent %u requests\n", __func__, cnt * 2);
-
- free(umad);
+ list->trid = mad_get_field64(umad_get_mad(umad), 0, IB_MAD_TRID_F);
return 0;
}
-static int rereg_recv_all(struct addr_data *a, ibmad_gid_t mgid,
- struct gid_list *list, unsigned cnt)
+static int rereg_recv_all(struct addr_data *a, void *umad, int len,
+ ibmad_gid_t mgid,
+ struct gid_list *list, unsigned cnt,
+ uint64_t comp_mask, uint8_t data[])
{
- uint8_t *umad, *mad;
- int len = 256;
+ uint8_t *mad;
uint64_t trid;
unsigned n, method, status;
int i;
info("%s...\n", __func__);
- umad = calloc(1, len + umad_size());
- if (!umad) {
- err("cannot alloc mem for umad: %s\n", strerror(errno));
- return -1;
- }
-
n = 0;
while (recv_res(a, umad, len) > 0) {
dbg("rereg_recv_all: done %d\n", n);
@@ -316,34 +329,30 @@ static int rereg_recv_all(struct addr_data *a, ibmad_gid_t mgid,
info("guid 0x%016" PRIx64
": method = %x status = %x. Resending\n",
get_guid_ho(list[i].gid), method, status);
- rereg_port(a, umad, len, mgid, &list[i]);
+ rereg_port(a, umad, len, mgid, &list[i],
+ comp_mask, data);
}
}
info("%s: got %u responses\n", __func__, n);
- free(umad);
return 0;
}
-static int rereg_query_all(struct addr_data *a, ibmad_gid_t mgid,
- struct gid_list *list, unsigned cnt)
+static int rereg_query_all(struct addr_data *a, void *umad, int len,
+ ibmad_gid_t mgid,
+ struct gid_list *list, unsigned cnt,
+ uint64_t comp_mask, uint8_t data[])
{
- uint8_t *umad, *mad;
- int len = 256;
+ uint8_t *mad;
unsigned method, status;
int i, ret;
info("%s...\n", __func__);
- umad = calloc(1, len + umad_size());
- if (!umad) {
- err("cannot alloc mem for umad: %s\n", strerror(errno));
- return -1;
- }
-
for (i = 0; i < cnt; i++) {
- ret = send_query(a, umad, len, mgid, list[i].gid);
+ ret = send_query(a, umad, len, mgid, list[i].gid,
+ comp_mask, data);
if (ret < 0) {
err("%s: rereg_send failed.\n", __func__);
continue;
@@ -367,7 +376,6 @@ static int rereg_query_all(struct addr_data *a, ibmad_gid_t mgid,
info("%s: %u queried.\n", __func__, cnt);
- free(umad);
return 0;
}
@@ -378,33 +386,18 @@ struct test_data {
struct gid_list *gids;
unsigned mgids_size;
struct gid_list *mgids;
+ const struct mcmember_params *params;
};
#define MAX_CLIENTS 100
static int run_port_rereg_test(struct addr_data *a, struct test_data *td)
{
- int cnt, i, size = td->gids_size;
-
- for (cnt = size; cnt;) {
- i = cnt > MAX_CLIENTS ? MAX_CLIENTS : cnt;
- rereg_send_all(a, td->mgids[0].gid, td->gids + (size - cnt), i);
- rereg_recv_all(a, td->mgids[0].gid, td->gids, size);
- cnt -= i;
- }
-
- rereg_query_all(a, td->mgids[0].gid, td->gids, size);
-
- return 0;
-}
-
-static int run_mcast_joins_test(struct addr_data *a, struct test_data *td)
-{
+ uint8_t data[256];
+ uint64_t comp_mask;
uint8_t *umad;
int len = 256;
- unsigned i, j;
-
- info("%s...\n", __func__);
+ int cnt, i, n, size = td->gids_size;
umad = calloc(1, len + umad_size());
if (!umad) {
@@ -412,38 +405,55 @@ static int run_mcast_joins_test(struct addr_data *a, struct test_data *td)
return -1;
}
- for (i = 0; i < td->gids_size; i++)
- for (j = 0; j < td->mgids_size; j++)
- if (send_create(a, umad, len,
- td->mgids[j].gid, td->gids[i].gid))
- return -1;
+ if (!td->params)
+ td->params = &mcmember_params_join;
- if (recv_all(a, umad, len) < 0)
- return -1;
+ comp_mask = build_mcm_rec(data, td->params);
+
+ for (cnt = size; cnt;) {
+ n = cnt > MAX_CLIENTS ? MAX_CLIENTS : cnt;
+ for (i = 0; i < n; i++) {
+ rereg_port(a, umad, len, td->mgids[0].gid,
+ &td->gids[size - cnt + i], comp_mask, data);
+ info("%s: sent %u requests\n", __func__, n * 2);
+ }
+ rereg_recv_all(a, umad, len, td->mgids[0].gid, td->gids, size,
+ comp_mask, data);
+ cnt -= i;
+ }
+
+ rereg_query_all(a, umad, len, td->mgids[0].gid, td->gids, size,
+ comp_mask, data);
free(umad);
return 0;
}
-static int run_mcast_leave_test(struct addr_data *a, struct test_data *td)
+static int run_mcast_member_test(struct addr_data *a, struct test_data *td,
+ int (*func)(struct addr_data *a,
+ uint8_t * umad, int len,
+ ibmad_gid_t mgid, ibmad_gid_t gid,
+ uint64_t comp_mask, uint8_t *data))
{
+ uint8_t data[256];
+ uint64_t comp_mask;
uint8_t *umad;
int len = 256;
unsigned i, j;
- info("%s...\n", __func__);
-
umad = calloc(1, len + umad_size());
if (!umad) {
err("cannot alloc mem for umad: %s\n", strerror(errno));
return -1;
}
+ comp_mask = build_mcm_rec(data, td->params);
+
for (i = 0; i < td->gids_size; i++)
for (j = 0; j < td->mgids_size; j++)
- if (send_leave(a, umad, len,
- td->mgids[j].gid, td->gids[i].gid))
+ if (func(a, umad, len, td->mgids[j].gid,
+ td->gids[i].gid, comp_mask, data))
return -1;
if (recv_all(a, umad, len) < 0)
@@ -454,6 +464,20 @@ static int run_mcast_leave_test(struct addr_data *a, struct test_data *td)
return 0;
}
+static int run_mcast_joins_test(struct addr_data *a, struct test_data *td)
+{
+ if (!td->params)
+ td->params = &mcmember_params_create;
+ return run_mcast_member_test(a, td, send_join);
+}
+
+static int run_mcast_leave_test(struct addr_data *a, struct test_data *td)
+{
+ if (!td->params)
+ td->params = &mcmember_params_join;
+ return run_mcast_member_test(a, td, send_leave);
+}
+
/* main stuff */
struct test {
@@ -462,14 +486,15 @@ struct test {
const char *description;
};
-static int run_test(const struct test *t, struct test_data *td)
+static int run_test(const struct test *t, struct test_data *td,
+ struct ibmad_port *mad_port)
{
struct addr_data addr;
int ret;
info("Running \'%s\'...\n", t->name);
- ib_resolve_smlid(&addr.dport, TMO);
+ ib_resolve_smlid_via(&addr.dport, TMO, mad_port);
if (!addr.dport.lid) {
/* dport.lid = 1; */
err("No SM. Exit.\n");
@@ -479,7 +504,7 @@ static int run_test(const struct test *t, struct test_data *td)
if (!addr.dport.qkey)
addr.dport.qkey = IB_DEFAULT_QP1_QKEY;
- addr.port = madrpc_portid();
+ addr.port = mad_rpc_portid(mad_port);
addr.agent = umad_register(addr.port, IB_SA_CLASS, 2, 0, NULL);
addr.timeout = TMO;
@@ -528,13 +553,55 @@ static int make_gids_list(ibmad_gid_t gid, unsigned n, struct gid_list **gid_lis
return i;
}
+static int parse_gid_str(ibmad_gid_t gid, char *str, uint64_t default_prefix)
+{
+ uint64_t guid, prefix = 0;
+ char *p, *e;
+
+ p = str;
+ while (isspace(*p))
+ p++;
+ e = strchr(p, '\n');
+ if (e) {
+ while (isspace(*e))
+ *e-- = '\0';
+ }
+
+ if (*p == '\0' || *p == '#')
+ return 1;
+
+ if (inet_pton(AF_INET6, p, gid) > 0)
+ return 0;
+
+ e = strchr(p, ':');
+ if (e) {
+ prefix = strtoull(p, NULL, 0);
+ guid = strtoull(e + 1, NULL, 0);
+ } else if (strlen(p) > 18) {
+ e = p + strlen(p) - 16;
+ guid = strtoull(e, NULL, 16);
+ *e = '\0';
+ prefix = strtoull(p, NULL, 0);
+ } else
+ guid = strtoull(p, NULL, 0);
+
+ if (!guid)
+ return -1;
+
+ if (!prefix)
+ prefix = default_prefix;
+
+ make_gid(gid, prefix, guid);
+
+ return 0;
+}
+
static int parse_gids_file(const char *guid_file, struct gid_list **gid_list)
{
char line[256];
+ ibmad_gid_t gid;
FILE *f;
- uint64_t guid, prefix;
struct gid_list *list = NULL;
- char *e;
unsigned list_size = 0;
int i = 0;
@@ -546,12 +613,8 @@ static int parse_gids_file(const char *guid_file, struct gid_list **gid_list)
}
while (fgets(line, sizeof(line), f)) {
- guid = strtoull(line, &e, 0);
- if (e && isxdigit(*e)) {
- prefix = guid;
- guid = strtoull(line, NULL, 0);
- } else
- prefix = DEFAULT_PREFIX;
+ if (parse_gid_str(gid, line, DEFAULT_PREFIX))
+ continue;
if (i >= list_size) {
list_size += 256;
@@ -564,7 +627,7 @@ static int parse_gids_file(const char *guid_file, struct gid_list **gid_list)
memset(&list[i], 0, 256 * sizeof(list[0]));
}
- make_gid(list[i].gid, prefix, guid);
+ memcpy(list[i].gid, gid, 16);
i++;
}
fclose(f);
@@ -622,6 +685,16 @@ int main(int argc, char **argv)
{"MGID", 1, 0, 'M'},
{"ipv4", 0, 0, 'i'},
{"increment", 1, 0, 'I'},
+ {"qkey", 1, 0, 'q'},
+ {"mlid", 1, 0, 'z'},
+ {"mtu", 1, 0, 'y'},
+ {"tclass", 1, 0, 't'},
+ {"pkey", 1, 0, 'p'},
+ {"rate", 1, 0, 'r'},
+ {"sl", 1, 0, 's'},
+ {"flowlabel", 1, 0, 'f'},
+ {"joinstate", 1, 0, 'j'},
+ {"proxy", 0, 0, 'x'},
{"version", 0, 0, 'V'},
{"verbose", 0, 0, 'v'},
{"help", 0, 0, 'h'},
@@ -636,14 +709,18 @@ int main(int argc, char **argv)
char opt_str[256];
int mgmt_classes[2] = { IB_SMI_CLASS, IB_SMI_DIRECT_CLASS };
+ struct mcmember_params params;
struct test_data tdata;
ibmad_gid_t gid, mgid = {};
uint64_t guid = 0;
const char *guid_file = NULL, *mgid_file = NULL;
+ struct ibmad_port *mad_port;
const struct test *t;
unsigned is_mgid = 0, is_ipv4 = 1, increment = 0;
int ret, ch;
+ params = null_params;
+
make_str_opts(opt_str, sizeof(opt_str), long_opts);
while ((ch = getopt_long(argc, argv, opt_str, long_opts, NULL)) != -1) {
@@ -652,18 +729,11 @@ int main(int argc, char **argv)
guid = strtoull(optarg, NULL, 0);
break;
case 'M':
- { char *e; uint64_t val1, val2;
- int len = strlen(optarg);
- if (len > 16)
- e = optarg + len - 16;
- else
- e = optarg;
- val2 = strtoull(e, NULL, 16);
- *e = '\0';
- val1 = strtoull(optarg, NULL, 16);
- make_gid(mgid, val1, val2);
- is_mgid = 1;
+ if (parse_gid_str(mgid, optarg, DEFAULT_MGID_PREFIX)) {
+ err("cannot parse MGID \'%s\'", optarg);
+ exit(2);
}
+ is_mgid = 1;
break;
case 'I':
increment = strtoul(optarg, NULL, 0);
@@ -674,6 +744,36 @@ int main(int argc, char **argv)
case 'm':
mgid_file = optarg;
break;
+ case 'q':
+ params.qkey = strtoul(optarg, NULL, 0);
+ break;
+ case 'z':
+ params.mlid = strtoul(optarg, NULL, 0);
+ break;
+ case 'y':
+ params.mtu = strtoul(optarg, NULL, 0);
+ break;
+ case 't':
+ params.tclass = strtoul(optarg, NULL, 0);
+ break;
+ case 'p':
+ params.pkey = strtoul(optarg, NULL, 0);
+ break;
+ case 'r':
+ params.rate = strtoul(optarg, NULL, 0);
+ break;
+ case 's':
+ params.sl = strtoul(optarg, NULL, 0);
+ break;
+ case 'f':
+ params.flow_label = strtoul(optarg, NULL, 0);
+ break;
+ case 'j':
+ params.join_state = strtoul(optarg, NULL, 0);
+ break;
+ case 'x':
+ params.proxy_join = 1;
+ break;
case 'v':
break;
case 'V':
@@ -686,7 +786,11 @@ int main(int argc, char **argv)
}
}
- madrpc_init(NULL, 0, mgmt_classes, 2);
+ mad_port = mad_rpc_open_port(NULL, 0, mgmt_classes, 2);
+ if (!mad_port) {
+ err("Cannot open local port...\n");
+ exit(-1);
+ }
memset(&tdata, 0, sizeof(tdata));
@@ -698,7 +802,7 @@ int main(int argc, char **argv)
guid = get_guid_ho(tdata.gids[0].gid);
} else {
ib_portid_t portid = {0};
- if (ib_resolve_self(&portid, NULL, &gid) < 0) {
+ if (ib_resolve_self_via(&portid, NULL, &gid, mad_port) < 0) {
err("Cannot resolve self port...\n");
exit(1);
}
@@ -717,7 +821,7 @@ int main(int argc, char **argv)
else if (is_ipv4)
ret = make_gids_list(mgid_ipoib, increment, &tdata.mgids);
else {
- make_gid(gid, 0xff00000000000000ULL, guid);
+ make_gid(gid, DEFAULT_MGID_PREFIX, guid);
ret = make_gids_list(gid, increment, &tdata.mgids);
}
@@ -725,14 +829,17 @@ int main(int argc, char **argv)
return ret;
tdata.mgids_size = ret;
+ if (memcmp(¶ms, &null_params, sizeof(params)))
+ tdata.params = ¶ms;
+
if (argc <= optind)
- return run_test(&tests[0], &tdata);
+ return run_test(&tests[0], &tdata, mad_port);
do {
t = find_test(tests, argv[optind]);
if (!t)
usage(argv[0], long_opts, tests);
- ret = run_test(t, &tdata);
+ ret = run_test(t, &tdata, mad_port);
if (ret)
break;
} while (argc > ++optind);
@@ -742,5 +849,7 @@ int main(int argc, char **argv)
if (tdata.mgids)
free(tdata.mgids);
+ mad_rpc_close_port(mad_port);
+
return ret;
}
diff --git a/tests/query_many.c b/tests/query_many.c
new file mode 100644
index 0000000..6e0b9f6
--- /dev/null
+++ b/tests/query_many.c
@@ -0,0 +1,309 @@
+/*
+ * Copyright (c) 2009 Voltaire, Inc. All rights reserved.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <getopt.h>
+#include <sys/time.h>
+
+#include <infiniband/umad.h>
+#include <infiniband/mad.h>
+
+static unsigned number_queries = 1;
+static uint8_t dr_path[64];
+static size_t dr_path_size = 0;
+static uint16_t attribute_id = IB_ATTR_NODE_INFO;
+static uint32_t attribute_mod = 0;
+
+static unsigned timeout = 100;
+static unsigned retries = 3;
+static unsigned verbose = 0;
+
+#define ERROR(fmt, ...) fprintf(stderr, "ERR: " fmt, ##__VA_ARGS__)
+#define VERBOSE(fmt, ...) if (verbose) fprintf(stderr, fmt, ##__VA_ARGS__)
+#define NOISE(fmt, ...) if (verbose > 1) fprintf(stderr, fmt, ##__VA_ARGS__)
+
+static const char *print_path(uint8_t path[], size_t path_cnt)
+{
+ static char buf[256];
+ int i, n = 0;
+ for (i = 0; i <= path_cnt; i++)
+ n += snprintf(buf + n, sizeof(buf) - n, "%u,", path[i]);
+ buf[n] = '\0';
+ return buf;
+}
+
+static size_t parse_direct_path(const char *str, uint8_t path[], size_t size)
+{
+ size_t i;
+
+ for (i = 0; i < size; i++) {
+ path[i] = strtoul(str, NULL, 0);
+ str = strchr(str, ',');
+ if (!str)
+ break;
+ str++;
+ }
+
+ return i;
+}
+
+static void build_umad_req(void *umad, uint8_t * path, unsigned path_cnt,
+ uint64_t trid, uint8_t method,
+ uint16_t attr_id, uint32_t attr_mod, uint64_t mkey)
+{
+ void *mad = umad_get_mad(umad);
+
+ memset(umad, 0, umad_size() + IB_MAD_SIZE);
+ umad_set_addr(umad, 0xffff, 0, 0, 0);
+ mad_set_field(mad, 0, IB_MAD_METHOD_F, method);
+ mad_set_field(mad, 0, IB_MAD_CLASSVER_F, 1);
+ mad_set_field(mad, 0, IB_MAD_MGMTCLASS_F, IB_SMI_DIRECT_CLASS);
+ mad_set_field(mad, 0, IB_MAD_BASEVER_F, 1);
+ mad_set_field(mad, 0, IB_DRSMP_HOPCNT_F, path_cnt);
+ mad_set_field(mad, 0, IB_DRSMP_HOPPTR_F, 0);
+ mad_set_field64(mad, 0, IB_MAD_TRID_F, trid);
+ mad_set_field(mad, 0, IB_DRSMP_DRDLID_F, 0xffff);
+ mad_set_field(mad, 0, IB_DRSMP_DRSLID_F, 0xffff);
+ mad_set_array(mad, 0, IB_DRSMP_PATH_F, path);
+ mad_set_field(mad, 0, IB_MAD_ATTRID_F, attr_id);
+ mad_set_field(mad, 0, IB_MAD_ATTRMOD_F, attr_mod);
+ mad_set_field64(mad, 0, IB_MAD_MKEY_F, mkey);
+}
+
+static void check_diff(const char *name, void *mad,
+ struct timeval *tv1, struct timeval *tv)
+{
+ unsigned long diff = (tv1->tv_sec - tv->tv_sec) * 1000000 +
+ tv1->tv_usec - tv->tv_usec;
+
+ if (diff > 1000) {
+ uint8_t path[256];
+ uint8_t method = mad_get_field(mad, 0, IB_MAD_METHOD_F);
+ uint64_t trid = mad_get_field64(mad, 0, IB_MAD_TRID_F);
+ uint16_t attr_id = mad_get_field(mad, 0, IB_MAD_ATTRID_F);
+ uint32_t attr_mod = mad_get_field(mad, 0, IB_MAD_ATTRMOD_F);
+ size_t path_cnt = mad_get_field(mad, 0, IB_DRSMP_HOPCNT_F);
+ mad_get_array(mad, 0, IB_DRSMP_PATH_F, path);
+ printf("LONG %s (%lu) %016" PRIx64 ": method %x, attr %x,"
+ " mod %x, path %s\n", name, diff, trid, method,
+ attr_id, attr_mod, print_path(path, path_cnt));
+ fflush(stdout);
+ }
+}
+
+static int send_query(int fd, int agent, void *umad, uint64_t trid,
+ uint8_t * path, size_t path_cnt, uint16_t attr_id,
+ uint32_t attr_mod)
+{
+ struct timeval tv, tv1;
+ int ret;
+
+ build_umad_req(umad, path, path_cnt, trid, IB_MAD_METHOD_GET, attr_id,
+ attr_mod, 0);
+
+ gettimeofday(&tv, NULL);
+
+ ret = umad_send(fd, agent, umad, IB_MAD_SIZE, timeout, retries);
+
+ gettimeofday(&tv1, NULL);
+
+ if (ret < 0) {
+ ERROR("umad_send failed: trid 0x%016" PRIx64
+ ", attr_id %x, attr_mod %x: %s\n",
+ trid, attr_id, attr_mod, strerror(errno));
+ return -1;
+ }
+
+ VERBOSE("send %016" PRIx64 ": attr %x, mod %x to %s\n", trid, attr_id,
+ attr_mod, print_path(path, path_cnt));
+
+ check_diff("SEND", umad_get_mad(umad), &tv1, &tv);
+
+ return ret;
+}
+
+static int recv_response(int fd, int agent, uint8_t * umad, uint8_t path[])
+{
+ struct timeval tv, tv1;
+ void *mad;
+ uint64_t trid;
+ uint32_t attr_mod;
+ uint16_t attr_id, status;
+ size_t path_size;
+ int len = IB_MAD_SIZE, ret;
+
+ gettimeofday(&tv, NULL);
+
+ do {
+ ret = umad_recv(fd, umad, &len, timeout);
+ } while (ret >= 0 && ret != agent);
+
+ gettimeofday(&tv1, NULL);
+
+ if (ret < 0 || umad_status(umad)) {
+ ERROR("umad_recv failed: umad status %x: %s\n",
+ umad_status(umad), strerror(errno));
+ return -1;
+ }
+
+ check_diff("RESP", umad_get_mad(umad), &tv1, &tv);
+
+ mad = umad_get_mad(umad);
+ status = mad_get_field(mad, 0, IB_DRSMP_STATUS_F);
+ trid = mad_get_field64(mad, 0, IB_MAD_TRID_F);
+ attr_id = mad_get_field(mad, 0, IB_MAD_ATTRID_F);
+ attr_mod = mad_get_field(mad, 0, IB_MAD_ATTRMOD_F);
+ path_size = mad_get_field(mad, 0, IB_DRSMP_HOPCNT_F);
+ mad_get_array(mad, 0, IB_DRSMP_PATH_F, path);
+
+ if (status) {
+ ERROR("error response 0x%016" PRIx64 ": attr_id %x"
+ ", attr_mod %x from %s with status %x\n", trid,
+ attr_id, attr_mod, print_path(path, path_size), status);
+ return -1;
+ }
+
+ VERBOSE("recv %016" PRIx64 ": attr %x, mod %x from %s\n", trid, attr_id,
+ attr_mod, print_path(path, path_size));
+
+ return ret;
+}
+
+static int query(int fd, int agent)
+{
+ uint8_t path[64] = { 0 };
+ uint64_t trid = 0x20090000;
+ void *umad;
+ unsigned n = 0;
+ int ret = 0;
+
+ umad = malloc(IB_MAD_SIZE + umad_size());
+ if (!umad)
+ return -ENOMEM;
+
+ while (n++ < number_queries)
+ send_query(fd, agent, umad, trid++, dr_path, dr_path_size,
+ attribute_id, attribute_mod);
+
+ n = 0;
+ do {
+ ret = recv_response(fd, agent, umad, path);
+ } while (ret >= 0 && ++n < number_queries);
+
+ free(umad);
+
+ return ret;
+}
+
+static int umad_query(char *card_name, unsigned int port_num)
+{
+ int fd, agent, ret;
+
+ ret = umad_init();
+ if (ret) {
+ ERROR("cannot init umad\n");
+ return -1;
+ }
+
+ fd = umad_open_port(card_name, port_num);
+ if (fd < 0) {
+ ERROR("cannot open umad port %s:%u: %s\n",
+ card_name ? card_name : "NULL", port_num,
+ strerror(errno));
+ return -1;
+ }
+
+ agent = umad_register(fd, IB_SMI_DIRECT_CLASS, 1, 0, NULL);
+ if (agent < 0) {
+ ERROR("cannot register SMI DR class for umad port %s:%u: %s\n",
+ card_name ? card_name : "NULL", port_num,
+ strerror(errno));
+ return -1;
+ }
+
+ ret = query(fd, agent);
+ if (ret)
+ ERROR("Failed.\n");
+
+ umad_unregister(fd, agent);
+ umad_close_port(fd);
+
+ umad_done();
+
+ return ret;
+}
+
+int main(int argc, char **argv)
+{
+ const struct option long_opts[] = {
+ {"number", 1, 0, 'n'},
+ {"drpath", 1, 0, 'd'},
+ {"attribute", 1, 0, 'a'},
+ {"modifier", 1, 0, 'm'},
+ {"Card", 1, 0, 'C'},
+ {"Port", 1, 0, 'P'},
+ {"timeout", 1, 0, 't'},
+ {"retries", 1, 0, 'r'},
+ {}
+ };
+ char *card_name = NULL;
+ unsigned int port_num = 0;
+ int ch, ret;
+
+ while (1) {
+ ch = getopt_long(argc, argv, "n:d:a:m:C:P:t:r:v", long_opts, NULL);
+ if (ch == -1)
+ break;
+ switch (ch) {
+ case 'n':
+ number_queries = strtoul(optarg, NULL, 0);
+ break;
+ case 'd':
+ dr_path_size = parse_direct_path(optarg, dr_path,
+ sizeof(dr_path));
+ break;
+ case 'a':
+ attribute_id = strtoul(optarg, NULL, 0);
+ break;
+ case 'm':
+ attribute_mod = strtoul(optarg, NULL, 0);
+ break;
+ case 'C':
+ card_name = optarg;
+ break;
+ case 'P':
+ port_num = strtoul(optarg, NULL, 0);
+ break;
+ case 't':
+ timeout = strtoul(optarg, NULL, 0);
+ break;
+ case 'r':
+ retries = strtoul(optarg, NULL, 0);
+ break;
+ case 'v':
+ verbose++;
+ break;
+ default:
+ printf("Usage: %s [-n num_queries] [-d path]"
+ " [-a attr] [-m mod]"
+ " [-C card_name] [-P port_num]"
+ " [-t timeout] [-r retries] [-v[v]]\n", argv[0]);
+ exit(2);
+ break;
+ }
+ }
+
+ ret = umad_query(card_name, port_num);
+
+ return ret;
+}
diff --git a/tests/subnet_discover.c b/tests/subnet_discover.c
new file mode 100644
index 0000000..44cd86e
--- /dev/null
+++ b/tests/subnet_discover.c
@@ -0,0 +1,649 @@
+/*
+ * Copyright (c) 2009 Voltaire, Inc. All rights reserved.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <getopt.h>
+
+#include <infiniband/umad.h>
+#include <infiniband/mad.h>
+
+#define MAX_HOPS 63
+
+struct port {
+ struct node *node;
+ uint64_t guid;
+ struct port *remote;
+ uint8_t port_info[IB_SMP_DATA_SIZE];
+};
+
+struct node {
+ uint64_t guid;
+ unsigned num_ports;
+ unsigned is_switch;
+ size_t path_size;
+ uint8_t path[64];
+ uint8_t node_info[IB_SMP_DATA_SIZE];
+ uint8_t node_desc[IB_SMP_DATA_SIZE];
+ uint8_t switch_info[IB_SMP_DATA_SIZE];
+ struct port ports[];
+};
+
+static struct node *node_array[32 * 1024];
+static unsigned node_count = 0;
+static unsigned trid_cnt = 0;
+static unsigned outstanding = 0;
+static unsigned max_outstanding = 8;
+static unsigned timeout = 100;
+static unsigned retries = 3;
+static unsigned verbose = 0;
+
+static unsigned total_mads = 0;
+static unsigned max_hops = 0;
+
+#define ERROR(fmt, ...) fprintf(stderr, "ERR: " fmt, ##__VA_ARGS__)
+#define VERBOSE(fmt, ...) if (verbose) fprintf(stderr, fmt, ##__VA_ARGS__)
+#define VERBOSE1(fmt, ...) if (verbose > 1) fprintf(stderr, fmt, ##__VA_ARGS__)
+#define VERBOSE2(fmt, ...) if (verbose > 2) fprintf(stderr, fmt, ##__VA_ARGS__)
+#define NOISE(fmt, ...) VERBOSE2(fmt, ##__VA_ARGS__)
+
+static const char *print_path(uint8_t path[], size_t path_cnt)
+{
+ static char buf[256];
+ int i, n = 0;
+ for (i = 0; i <= path_cnt; i++)
+ n += snprintf(buf + n, sizeof(buf) - n, "%u,", path[i]);
+ buf[n] = '\0';
+ return buf;
+}
+
+#define DBG_DUMP_FUNC(name) static void dbg_dump_##name(void *data) \
+{ \
+ char buf[2048]; \
+ mad_dump_##name(buf, sizeof(buf), data, IB_SMP_DATA_SIZE); \
+ NOISE("### "#name":\n%s\n", buf); \
+}
+
+DBG_DUMP_FUNC(nodeinfo);
+DBG_DUMP_FUNC(nodedesc);
+DBG_DUMP_FUNC(portinfo);
+DBG_DUMP_FUNC(switchinfo);
+
+static void build_umad_req(void *umad, uint8_t path[], unsigned path_cnt,
+ uint64_t trid, uint8_t method,
+ uint16_t attr_id, uint32_t attr_mod, uint64_t mkey)
+{
+ void *mad = umad_get_mad(umad);
+
+ memset(umad, 0, umad_size() + IB_MAD_SIZE);
+ umad_set_addr(umad, 0xffff, 0, 0, 0);
+ mad_set_field(mad, 0, IB_MAD_METHOD_F, method);
+ mad_set_field(mad, 0, IB_MAD_CLASSVER_F, 1);
+ mad_set_field(mad, 0, IB_MAD_MGMTCLASS_F, IB_SMI_DIRECT_CLASS);
+ mad_set_field(mad, 0, IB_MAD_BASEVER_F, 1);
+ mad_set_field(mad, 0, IB_DRSMP_HOPCNT_F, path_cnt);
+ mad_set_field(mad, 0, IB_DRSMP_HOPPTR_F, 0);
+ mad_set_field64(mad, 0, IB_MAD_TRID_F, trid);
+ mad_set_field(mad, 0, IB_DRSMP_DRDLID_F, 0xffff);
+ mad_set_field(mad, 0, IB_DRSMP_DRSLID_F, 0xffff);
+ mad_set_array(mad, 0, IB_DRSMP_PATH_F, path);
+ mad_set_field(mad, 0, IB_MAD_ATTRID_F, attr_id);
+ mad_set_field(mad, 0, IB_MAD_ATTRMOD_F, attr_mod);
+ mad_set_field64(mad, 0, IB_MAD_MKEY_F, mkey);
+}
+
+static int send_request(int fd, int agent, uint64_t trid, uint8_t * path,
+ size_t path_cnt, uint16_t attr_id, uint32_t attr_mod)
+{
+ uint8_t umad[IB_MAD_SIZE + umad_size()];
+ int ret;
+
+ build_umad_req(umad, path, path_cnt, trid, IB_MAD_METHOD_GET, attr_id,
+ attr_mod, 0);
+
+ ret = umad_send(fd, agent, umad, IB_MAD_SIZE, timeout, retries);
+ if (ret < 0) {
+ ERROR("umad_send failed: trid 0x%016" PRIx64
+ ", attr_id %x, attr_mod %x: %s\n",
+ trid, attr_id, attr_mod, strerror(errno));
+ return -1;
+ }
+
+ VERBOSE1("send %016" PRIx64 ": attr %x, mod %x to %s\n", trid, attr_id,
+ attr_mod, print_path(path, path_cnt));
+
+ return ret;
+}
+
+static struct request_queue {
+ struct request_queue *next;
+ uint64_t trid;
+ uint16_t attr_id;
+ uint32_t attr_mod;
+ size_t path_cnt;
+ uint8_t path[0];
+} request_queue;
+
+static struct request_queue *request_last = &request_queue;
+
+static unsigned tr_table_size;
+static struct request_queue **tr_table;
+
+static void add_to_tr_table(struct request_queue *q, uint64_t trid)
+{
+ unsigned n = trid >> 16;
+ if (n >= tr_table_size) {
+ unsigned new_size = tr_table_size ? tr_table_size * 2 : 4096;
+ if (n > new_size)
+ new_size = n + 1;
+ tr_table = realloc(tr_table, new_size * sizeof(tr_table[0]));
+ if (!tr_table) {
+ ERROR("cannot realloc request table\n");
+ tr_table_size = 0;
+ return;
+ }
+ memset(tr_table + tr_table_size, 0,
+ (new_size - tr_table_size) * sizeof(tr_table[0]));
+ tr_table_size = new_size;
+ }
+
+ tr_table[n] = q;
+}
+
+static void clean_from_tr_table(uint64_t trid)
+{
+ unsigned n = (trid >> 16) & 0xffff;
+ if (n >= tr_table_size) {
+ ERROR("invalid request table index %u\n", n);
+ return;
+ }
+ free(tr_table[n]);
+ tr_table[n] = NULL;
+}
+
+static void free_unresponded()
+{
+ struct request_queue *q;
+ unsigned i;
+
+ for (i = 0 ; i < tr_table_size; i++) {
+ if (!(q = tr_table[i]))
+ continue;
+ fprintf(stderr, "Unresponded transaction %016" PRIx64 ": %s "
+ "attr_id %x, attr_mod %x\n", q->trid,
+ print_path(q->path, q->path_cnt), q->attr_id,
+ q->attr_mod);
+ free(q);
+ }
+}
+
+static void run_request_queue(int fd, int agent)
+{
+ struct request_queue *q = request_queue.next;
+
+ while (q) {
+ if (outstanding >= max_outstanding)
+ break;
+ if (send_request(fd, agent, q->trid, q->path, q->path_cnt,
+ q->attr_id, q->attr_mod) < 0)
+ break;
+ q = q->next;
+ outstanding++;
+ total_mads++;
+ }
+ request_queue.next = q;
+ if (!q)
+ request_last = &request_queue;
+}
+
+static int queue_request(uint64_t trid, uint8_t * path, size_t path_cnt,
+ uint16_t attr_id, uint32_t attr_mod)
+{
+ struct request_queue *q = malloc(sizeof(*q) + path_cnt + 1);
+ if (!q)
+ return -1;
+ q->next = NULL;
+ q->trid = trid;
+ q->attr_id = attr_id;
+ q->attr_mod = attr_mod;
+ memcpy(q->path, path, path_cnt + 1);
+ q->path_cnt = path_cnt;
+
+ request_last->next = q;
+ request_last = q;
+
+ add_to_tr_table(q, trid);
+
+ return 0;
+}
+
+static int send_query(int fd, int agent, unsigned node_id, uint8_t path[],
+ size_t path_cnt, uint16_t attr_id, uint32_t attr_mod)
+{
+ uint64_t trid;
+ int ret;
+
+ trid = (trid_cnt++ << 16) | (node_id & 0xffff);
+
+ ret = queue_request(trid, path, path_cnt, attr_id, attr_mod);
+ if (ret < 0) {
+ ERROR("queue failed: trid 0x%016" PRIx64 ", attr_id %x,"
+ " attr_mod %x\n", trid, attr_id, attr_mod);
+ return -1;
+ }
+
+ VERBOSE1("queue %016" PRIx64 ": attr %x, mod %x to %s\n", trid, attr_id,
+ attr_mod, print_path(path, path_cnt));
+
+ run_request_queue(fd, agent);
+
+ return ret;
+}
+
+static int recv_response(int fd, int agent, uint8_t * umad, size_t length)
+{
+ int len = length, ret;
+
+ do {
+ ret = umad_recv(fd, umad, &len, timeout);
+ } while (ret >= 0 && ret != agent);
+
+ if (ret < 0 || umad_status(umad)) {
+ ERROR("umad_recv failed: umad status %x: %s\n",
+ umad_status(umad), strerror(errno));
+ return len > umad_size() ? 1 : -1;
+ }
+
+ return 0;
+}
+
+static int query_node_info(int fd, int agent, unsigned node_id,
+ uint8_t path[], size_t path_cnt)
+{
+ return send_query(fd, agent, node_id, path, path_cnt,
+ IB_ATTR_NODE_INFO, 0);
+}
+
+static int query_node_desc(int fd, int agent, unsigned node_id,
+ uint8_t path[], size_t path_cnt)
+{
+ return send_query(fd, agent, node_id, path, path_cnt,
+ IB_ATTR_NODE_DESC, 0);
+}
+
+static int query_switch_info(int fd, int agent, unsigned node_id,
+ uint8_t path[], size_t path_cnt)
+{
+ return send_query(fd, agent, node_id, path, path_cnt,
+ IB_ATTR_SWITCH_INFO, 0);
+}
+
+static int query_port_info(int fd, int agent, unsigned node_id,
+ uint8_t path[], size_t path_cnt, unsigned port_num)
+{
+ return send_query(fd, agent, node_id, path, path_cnt,
+ IB_ATTR_PORT_INFO, port_num);
+}
+
+static int add_node(uint8_t * node_info, uint8_t path[], size_t path_size)
+{
+ struct node *node;
+ unsigned i, num_ports = mad_get_field(node_info, 0, IB_NODE_NPORTS_F);
+
+ node = malloc(sizeof(*node) + (num_ports + 1) * sizeof(node->ports[0]));
+ if (!node)
+ return -1;
+ memset(node, 0,
+ sizeof(*node) + (num_ports + 1) * sizeof(node->ports[0]));
+
+ node->num_ports = num_ports;
+ node->guid = mad_get_field64(node_info, 0, IB_NODE_GUID_F);
+ node->is_switch = ((mad_get_field(node_info, 0, IB_NODE_TYPE_F)) ==
+ IB_NODE_SWITCH);
+ memcpy(node->path, path, path_size + 1);
+ node->path_size = path_size;
+ memcpy(node->node_info, node_info, sizeof(node->node_info));
+ for (i = 0; i <= num_ports; i++)
+ node->ports[i].node = node;
+
+ node_array[node_count] = node;
+
+ return node_count++;
+}
+
+static int find_node(uint8_t * node_info)
+{
+ uint64_t guid = mad_get_field64(node_info, 0, IB_NODE_GUID_F);
+ unsigned i;
+
+ for (i = 0; i < node_count; i++)
+ if (node_array[i]->guid == guid)
+ return i;
+ return -1;
+}
+
+static int process_port_info(void *umad, unsigned node_id, int fd, int agent,
+ uint8_t path[], size_t path_cnt)
+{
+ struct node *node = node_array[node_id];
+ struct port *port;
+ uint8_t *port_info = umad + umad_size() + IB_SMP_DATA_OFFS;
+ unsigned port_num, local_port;
+
+ dbg_dump_portinfo(port_info);
+
+ port_num = mad_get_field(umad_get_mad(umad), 0, IB_MAD_ATTRMOD_F);
+ local_port = mad_get_field(port_info, 0, IB_PORT_LOCAL_PORT_F);
+
+ port = &node->ports[port_num];
+ memcpy(port->port_info, port_info, sizeof(port->port_info));
+
+ if (port_num &&
+ mad_get_field(port_info, 0, IB_PORT_PHYS_STATE_F) == 5 &&
+ ((node->is_switch && port_num != local_port) ||
+ (node_id == 0 && port_num == local_port)) &&
+ path_cnt++ < MAX_HOPS) {
+ if (path_cnt > max_hops)
+ max_hops = path_cnt;
+ path[path_cnt] = port_num;
+ return query_node_info(fd, agent, node_id, path, path_cnt);
+ }
+
+ return 0;
+}
+
+static int process_switch_info(unsigned node_id, uint8_t * switch_info)
+{
+ struct node *node = node_array[node_id];
+
+ dbg_dump_switchinfo(switch_info);
+ memcpy(node->switch_info, switch_info, sizeof(node->switch_info));
+
+ return 0;
+}
+
+static int process_node_desc(unsigned node_id, uint8_t * node_desc)
+{
+ struct node *node = node_array[node_id];
+
+ dbg_dump_nodedesc(node_desc);
+ memcpy(node->node_desc, node_desc, sizeof(node->node_desc));
+
+ return 0;
+}
+
+static void connect_ports(unsigned node1_id, unsigned port1_num,
+ unsigned node2_id, unsigned port2_num)
+{
+ struct port *port1 = &node_array[node1_id]->ports[port1_num];
+ struct port *port2 = &node_array[node2_id]->ports[port2_num];
+ VERBOSE1("connecting %u:%u <--> %u:%u\n",
+ node1_id, port1_num, node2_id, port2_num);
+ port1->remote = port2;
+ port2->remote = port1;
+}
+
+static int process_node(void *umad, unsigned remote_id, int fd, int agent,
+ uint8_t path[], size_t path_cnt)
+{
+ struct node *node;
+ uint8_t *node_info = umad_get_mad(umad) + IB_SMP_DATA_OFFS;
+ unsigned port_num = mad_get_field(node_info, 0, IB_NODE_LOCAL_PORT_F);
+ unsigned node_is_new = 0;
+ int i, id;
+
+ dbg_dump_nodeinfo(node_info);
+
+ if ((id = find_node(node_info)) < 0) {
+ id = add_node(node_info, path, path_cnt);
+ if (id < 0)
+ return -1;
+ node_is_new = 1;
+ }
+
+ node = node_array[id];
+
+ VERBOSE("%-5s %-6s with guid 0x%" PRIx64 " discovered at %s\n",
+ node_is_new ? "new" : "known",
+ node->is_switch ? "Switch" : "Ca", node->guid,
+ print_path(path, path_cnt));
+
+ node->ports[port_num].guid =
+ mad_get_field64(node_info, 0, IB_NODE_PORT_GUID_F);
+
+ if (id) /* skip connect for very first node */
+ connect_ports(id, port_num, remote_id, path[path_cnt]);
+
+ if (!node_is_new)
+ return 0;
+
+ query_node_desc(fd, agent, id, path, path_cnt);
+
+ if (node->is_switch)
+ query_switch_info(fd, agent, id, path, path_cnt);
+
+ for (i = !node->is_switch; i <= node->num_ports; i++)
+ query_port_info(fd, agent, id, path, path_cnt, i);
+
+ return 0;
+}
+
+static int recv_smp_resp(int fd, int agent, uint8_t * umad, uint8_t path[])
+{
+ void *mad;
+ uint64_t trid;
+ uint8_t method;
+ uint16_t status;
+ uint16_t attr_id;
+ uint32_t attr_mod;
+ size_t path_cnt;
+ unsigned node_id;
+ int ret;
+
+ ret = recv_response(fd, agent, umad, IB_MAD_SIZE);
+
+ mad = umad_get_mad(umad);
+ status = mad_get_field(mad, 0, IB_DRSMP_STATUS_F);
+ method = mad_get_field(mad, 0, IB_MAD_METHOD_F);
+ trid = mad_get_field64(mad, 0, IB_MAD_TRID_F);
+ attr_id = mad_get_field(mad, 0, IB_MAD_ATTRID_F);
+ attr_mod = mad_get_field(mad, 0, IB_MAD_ATTRMOD_F);
+ path_cnt = mad_get_field(mad, 0, IB_DRSMP_HOPCNT_F);
+ mad_get_array(mad, 0, IB_DRSMP_PATH_F, path);
+
+ if (method != IB_MAD_METHOD_GET)
+ return 0;
+
+ outstanding--;
+ run_request_queue(fd, agent);
+
+ if (ret < 0)
+ return ret;
+ else if (ret || status) {
+ ERROR("error response 0x%016" PRIx64 ": attr_id %x"
+ ", attr_mod %x from %s with status %x\n", trid,
+ attr_id, attr_mod, print_path(path, path_cnt), status);
+ return -1;
+ }
+
+ clean_from_tr_table(trid);
+
+ node_id = trid & 0xffff;
+
+ VERBOSE1("recv %016" PRIx64 ": attr %x, mod %x from %s\n", trid,
+ attr_id, attr_mod, print_path(path, path_cnt));
+
+ switch (attr_id) {
+ case IB_ATTR_NODE_INFO:
+ process_node(umad, node_id, fd, agent, path, path_cnt);
+ break;
+ case IB_ATTR_NODE_DESC:
+ process_node_desc(node_id, mad + IB_SMP_DATA_OFFS);
+ break;
+ case IB_ATTR_SWITCH_INFO:
+ process_switch_info(node_id, mad + IB_SMP_DATA_OFFS);
+ break;
+ case IB_ATTR_PORT_INFO:
+ process_port_info(umad, node_id, fd, agent, path, path_cnt);
+ break;
+ default:
+ VERBOSE("unsolicited response 0x%016" PRIx64 ": attr_id %x"
+ ", attr_mod %x\n", trid, attr_id, attr_mod);
+ return 0;
+ }
+
+ return ret;
+}
+
+static int discover(int fd, int agent)
+{
+ uint8_t umad[IB_MAD_SIZE + umad_size()];
+ uint8_t path[64] = { 0 };
+ int ret;
+
+ ret = query_node_info(fd, agent, 0, path, 0);
+ if (ret < 0)
+ return ret;
+
+ while (outstanding)
+ if (recv_smp_resp(fd, agent, umad, path))
+ ret = 1;
+
+ free_unresponded();
+
+ return ret;
+}
+
+static int umad_discover(char *card_name, unsigned int port_num)
+{
+ int fd, agent, ret;
+
+ ret = umad_init();
+ if (ret) {
+ ERROR("cannot init umad\n");
+ return -1;
+ }
+
+ fd = umad_open_port(card_name, port_num);
+ if (fd < 0) {
+ ERROR("cannot open umad port %s:%u: %s\n",
+ card_name ? card_name : "NULL", port_num,
+ strerror(errno));
+ return -1;
+ }
+
+ agent = umad_register(fd, IB_SMI_DIRECT_CLASS, 1, 0, NULL);
+ if (agent < 0) {
+ ERROR("cannot register SMI DR class for umad port %s:%u: %s\n",
+ card_name ? card_name : "NULL", port_num,
+ strerror(errno));
+ return -1;
+ }
+
+ ret = discover(fd, agent);
+ if (ret)
+ fprintf(stderr, "\nThere are problems during discovery.\n");
+
+ umad_unregister(fd, agent);
+ umad_close_port(fd);
+
+ umad_done();
+
+ return ret;
+}
+
+static void print_subnet()
+{
+ struct node *node;
+ struct port *local, *remote;
+ unsigned i, j;
+
+ printf("\n# The subnet discovered using %u mads, reaching %d hops\n\n",
+ total_mads, max_hops);
+
+ for (i = 0; i < node_count; i++) {
+ node = node_array[i];
+ printf("%s %u \"%s-%016" PRIx64 "\" \t# %s %s\n",
+ node->is_switch ? "Switch" : "Ca", node->num_ports,
+ node->is_switch ? "S" : "H", node->guid,
+ print_path(node->path, node->path_size), node->node_desc);
+ for (j = 1; j <= node->num_ports; j++) {
+ local = &node->ports[j];
+ remote = local->remote;
+ if (!remote)
+ continue;
+ printf("[%u] \t\"%s-%016" PRIx64 "\"[%lu] \t# %s\n", j,
+ remote->node->is_switch ? "S" : "H",
+ remote->node->guid, remote - remote->node->ports,
+ remote->node->node_desc);
+ }
+ printf("\n");
+ }
+}
+
+int main(int argc, char **argv)
+{
+ const struct option long_opts[] = {
+ {"Card", 1, 0, 'C'},
+ {"Port", 1, 0, 'P'},
+ {"maxsmps", 1, 0, 'n'},
+ {"timeout", 1, 0, 't'},
+ {"retries", 1, 0, 'r'},
+ {"verbose", 0, 0, 'v'},
+ {"help", 0, 0, 'h'},
+ {}
+ };
+ char *card_name = NULL;
+ unsigned int port_num = 0;
+ int ch, ret;
+
+ while (1) {
+ ch = getopt_long(argc, argv, "C:P:n:t:r:vh", long_opts, NULL);
+ if (ch == -1)
+ break;
+ switch (ch) {
+ case 'C':
+ card_name = optarg;
+ break;
+ case 'P':
+ port_num = strtoul(optarg, NULL, 0);
+ break;
+ case 'n':
+ max_outstanding = strtoul(optarg, NULL, 0);
+ if (!max_outstanding)
+ max_outstanding = -1;
+ break;
+ case 't':
+ timeout = strtoul(optarg, NULL, 0);
+ break;
+ case 'r':
+ retries = strtoul(optarg, NULL, 0);
+ break;
+ case 'v':
+ verbose++;
+ break;
+ case 'h':
+ default:
+ printf("usage: %s [-C card_name] [-P port_num]"
+ " [-n maxsmps] [-t timeout] [-r retries]"
+ " [-v[v]]\n", argv[0]);
+ exit(2);
+ break;
+ }
+ }
+
+ ret = umad_discover(card_name, port_num);
+
+ print_subnet();
+
+ return ret;
+}
diff --git a/umad2sim/sim_client.c b/umad2sim/sim_client.c
index 30430b7..cec72d9 100644
--- a/umad2sim/sim_client.c
+++ b/umad2sim/sim_client.c
@@ -45,7 +45,6 @@
#include <arpa/inet.h>
#include <netdb.h>
-#include <infiniband/common.h>
#include <infiniband/mad.h>
#include <ibsim.h>
@@ -60,6 +59,7 @@
#endif
static unsigned int remote_mode = 0;
+static char* socket_basename;
static int sim_ctl(struct sim_client *sc, int type, void *data, int len)
{
@@ -143,11 +143,10 @@ static size_t make_name(union name_t *name, char *host, unsigned port,
static char *get_name(union name_t *name)
{
- if (remote_mode) {
+ if (remote_mode)
return inet_ntoa(name->name_i.sin_addr);
- } else {
+ else
return name->name_u.sun_path + 1;
- }
}
static int sim_attach(int fd, union name_t *name, size_t size)
@@ -159,8 +158,7 @@ static int sim_attach(int fd, union name_t *name, size_t size)
DEBUG("attempt to connect to %s (attempt %d)",
get_name(name), retries);
- if ((r =
- connect(fd, (struct sockaddr *)name, size)) >= 0)
+ if ((r = connect(fd, (struct sockaddr *)name, size)) >= 0)
break;
if (r < 0 && errno == ECONNREFUSED) {
@@ -175,12 +173,16 @@ static int sim_attach(int fd, union name_t *name, size_t size)
return 0;
}
-static int sim_connect(struct sim_client *sc, int id, int qp, char *nodeid)
+static int sim_connect(struct sim_client *sc, int id, int qp, char *nodeid,
+ char *issm)
{
struct sim_client_info info = { 0 };
info.id = id;
- info.issm = 0;
+ if (issm)
+ info.issm = 1;
+ else
+ info.issm = 0;
info.qp = qp;
if (nodeid)
@@ -202,7 +204,7 @@ static int sim_disconnect(struct sim_client *sc)
return sim_ctl(sc, SIM_CTL_DISCONNECT, 0, 0);
}
-static int sim_init(struct sim_client *sc, int qp, char *nodeid)
+static int sim_init(struct sim_client *sc, char *nodeid, char *issm)
{
union name_t name;
socklen_t size;
@@ -214,12 +216,15 @@ static int sim_init(struct sim_client *sc, int qp, char *nodeid)
connect_port = getenv("IBSIM_SERVER_PORT");
connect_host = getenv("IBSIM_SERVER_NAME");
+ socket_basename = getenv("IBSIM_SOCKNAME");
+
+ if(!socket_basename)
+ socket_basename = SIM_BASENAME;
if (connect_host && *connect_host)
remote_mode = 1;
- DEBUG("init client pid=%d, qp=%d nodeid=%s",
- pid, qp, nodeid ? nodeid : "none");
+ DEBUG("init client pid=%d, nodeid=%s", pid, nodeid ? nodeid : "none");
if ((fd = socket(remote_mode ? PF_INET : PF_LOCAL, SOCK_DGRAM, 0)) < 0)
IBPANIC("can't get socket (fd)");
@@ -227,7 +232,7 @@ static int sim_init(struct sim_client *sc, int qp, char *nodeid)
if ((ctlfd = socket(remote_mode ? PF_INET : PF_LOCAL, SOCK_DGRAM, 0)) < 0)
IBPANIC("can't get socket (ctlfd)");
- size = make_name(&name, NULL, 0, "%s:ctl%d", SIM_BASENAME, pid);
+ size = make_name(&name, NULL, 0, "%s:ctl%d", socket_basename, pid);
if (bind(ctlfd, (struct sockaddr *)&name, size) < 0)
IBPANIC("can't bind ctl socket");
@@ -236,13 +241,13 @@ static int sim_init(struct sim_client *sc, int qp, char *nodeid)
pid, ctlfd, get_name(&name));
port = connect_port ? atoi(connect_port) : IBSIM_DEFAULT_SERVER_PORT;
- size = make_name(&name, connect_host, port, "%s:ctl", SIM_BASENAME);
+ size = make_name(&name, connect_host, port, "%s:ctl", socket_basename);
sim_attach(ctlfd, &name, size);
sc->fd_ctl = ctlfd;
- size = make_name(&name, NULL, 0, "%s:in%d", SIM_BASENAME, pid);
+ size = make_name(&name, NULL, 0, "%s:in%d", socket_basename, pid);
if (bind(fd, (struct sockaddr *)&name, size) < 0)
IBPANIC("can't bind input socket");
@@ -253,13 +258,13 @@ static int sim_init(struct sim_client *sc, int qp, char *nodeid)
IBPANIC("can't read data from bound socket");
port = ntohs(name.name_i.sin_port);
- sc->clientid = sim_connect(sc, remote_mode ? port : pid, qp, nodeid);
+ sc->clientid = sim_connect(sc, remote_mode ? port : pid, 0, nodeid, issm);
if (sc->clientid < 0)
IBPANIC("connect failed");
port = connect_port ? atoi(connect_port) : IBSIM_DEFAULT_SERVER_PORT;
size = make_name(&name, connect_host, port + sc->clientid + 1,
- "%s:out%d", SIM_BASENAME, sc->clientid);
+ "%s:out%d", socket_basename, sc->clientid);
sim_attach(fd, &name, size);
@@ -280,31 +285,35 @@ int sim_client_set_sm(struct sim_client *sc, unsigned issm)
return sim_ctl(sc, SIM_CTL_SET_ISSM, &issm, sizeof(int));
}
-int sim_client_init(struct sim_client *sc, char *nodeid)
+int sim_client_init(struct sim_client *sc)
{
- if (!nodeid)
- nodeid = getenv("SIM_HOST");
- if (sim_init(sc, 0, nodeid) < 0)
+ char *nodeid;
+ char *issm;
+
+ nodeid = getenv("SIM_HOST");
+ issm = getenv("SIM_SET_ISSM");
+ if (sim_init(sc, nodeid, issm) < 0)
return -1;
- if (sim_ctl(sc, SIM_CTL_GET_VENDOR, &sc->vendor, sizeof(sc->vendor)) <
- 0)
+ if (sim_ctl(sc, SIM_CTL_GET_VENDOR, &sc->vendor,
+ sizeof(sc->vendor)) < 0)
goto _exit;
if (sim_ctl(sc, SIM_CTL_GET_NODEINFO, sc->nodeinfo,
sizeof(sc->nodeinfo)) < 0)
goto _exit;
- sc->portinfo[0] = 0;
+
+ sc->portinfo[0] = 0; // portno requested
if (sim_ctl(sc, SIM_CTL_GET_PORTINFO, sc->portinfo,
sizeof(sc->portinfo)) < 0)
goto _exit;
if (sim_ctl(sc, SIM_CTL_GET_PKEYS, sc->pkeys, sizeof(sc->pkeys)) < 0)
goto _exit;
- if (getenv("SIM_SET_ISSM"))
+ if (issm)
sim_client_set_sm(sc, 1);
return 0;
_exit:
sim_disconnect(sc);
sc->fd_ctl = sc->fd_pktin = sc->fd_pktout = -1;
- return 0;
+ return -1;
}
void sim_client_exit(struct sim_client *sc)
diff --git a/umad2sim/sim_client.h b/umad2sim/sim_client.h
index 605b305..80ed442 100644
--- a/umad2sim/sim_client.h
+++ b/umad2sim/sim_client.h
@@ -47,7 +47,7 @@ struct sim_client {
};
extern int sim_client_set_sm(struct sim_client *sc, unsigned issm);
-extern int sim_client_init(struct sim_client *sc, char *nodeid);
+extern int sim_client_init(struct sim_client *sc);
extern void sim_client_exit(struct sim_client *sc);
#endif /* _SIM_CLIENT_H_ */
diff --git a/umad2sim/umad2sim.c b/umad2sim/umad2sim.c
index f896540..55440ec 100644
--- a/umad2sim/umad2sim.c
+++ b/umad2sim/umad2sim.c
@@ -50,11 +50,9 @@
#include <dlfcn.h>
#include <netinet/in.h>
-#include <infiniband/common.h>
#include <infiniband/umad.h>
#include <infiniband/mad.h>
-#include <ibsim.h>
#include <sim_client.h>
#ifdef UMAD2SIM_NOISY_DEBUG
@@ -96,9 +94,16 @@ static ssize_t(*real_write) (int fd, const void *buf, size_t count);
static int (*real_poll) (struct pollfd * pfds, nfds_t nfds, int timeout);
static int (*real_ioctl) (int d, int request, ...);
static DIR *(*real_opendir) (const char *dir);
+#if __GLIBC_PREREQ(2,10)
+static int (*real_scandir) (const char *dir, struct dirent *** namelist,
+ int (*filter) (const struct dirent *),
+ int (*compar) (const struct dirent **,
+ const struct dirent **));
+#else
static int (*real_scandir) (const char *dir, struct dirent *** namelist,
int (*filter) (const struct dirent *),
int (*compar) (const void *, const void *));
+#endif
static char sysfs_infiniband_dir[] = SYS_INFINIBAND;
static char sysfs_infiniband_mad_dir[] = IB_UMAD_ABI_DIR;
@@ -443,8 +448,8 @@ static ssize_t umad2sim_write(struct umad2sim_dev *dev,
{ static int err_count;
if (++err_count == 15)
return -1;
- if (mad_get_field(umad_get_mad(umad), 0, IB_MAD_METHOD_F) == 0x7) {
- printf("Drop trap repress...\n");
+ if (mad_get_field(umad_get_mad(umad), 0, IB_MAD_METHOD_F) == IB_MAD_METHOD_TRAP_REPRESS) {
+ printf("Dropping trap repress...\n");
return -1;
}
}
@@ -563,7 +568,7 @@ static struct umad2sim_dev *umad2sim_dev_create(unsigned num, const char *name)
dev->num = num;
strncpy(dev->name, name, sizeof(dev->name) - 1);
- if (sim_client_init(&dev->sim_client, NULL) < 0)
+ if (sim_client_init(&dev->sim_client) < 0)
goto _error;
dev->port = mad_get_field(&dev->sim_client.portinfo, 0,
@@ -696,9 +701,15 @@ DIR *opendir(const char *path)
return real_opendir(path);
}
+#if __GLIBC_PREREQ(2,10)
+int scandir(const char *path, struct dirent ***namelist,
+ int (*filter) (const struct dirent *),
+ int (*compar) (const struct dirent **, const struct dirent **))
+#else
int scandir(const char *path, struct dirent ***namelist,
int (*filter) (const struct dirent *),
int (*compar) (const void *, const void *))
+#endif
{
char new_path[4096];
@@ -815,7 +826,7 @@ int ioctl(int fd, unsigned long request, ...)
return real_ioctl(fd, request, arg);
}
-int poll(struct pollfd *pfds, unsigned long nfds, int timeout)
+int poll(struct pollfd *pfds, nfds_t nfds, int timeout)
{
int saved_fds[nfds];
unsigned i;
@@ -828,7 +839,8 @@ int poll(struct pollfd *pfds, unsigned long nfds, int timeout)
struct umad2sim_dev *dev = devices[pfds[i].fd - 1024];
saved_fds[i] = pfds[i].fd;
pfds[i].fd = dev->sim_client.fd_pktin;
- }
+ } else
+ saved_fds[i] = 0;
}
ret = real_poll(pfds, nfds, timeout);
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-ofed/ibsim.git
More information about the Pkg-ofed-commits
mailing list