aboutsummaryrefslogtreecommitdiff
path: root/contrib/ofed/infiniband-diags
diff options
context:
space:
mode:
authorHans Petter Selasky <hselasky@FreeBSD.org>2017-08-02 16:00:30 +0000
committerHans Petter Selasky <hselasky@FreeBSD.org>2017-08-02 16:00:30 +0000
commitd6b92ffa990dc57d8a969a98e3ca4e25ba39cbb2 (patch)
tree8cca73c0fa75739adf10581b9e68d682f63048f3 /contrib/ofed/infiniband-diags
parent434b6d2073f936acc361b1e343dd9615036e1cd9 (diff)
downloadsrc-d6b92ffa990dc57d8a969a98e3ca4e25ba39cbb2.tar.gz
src-d6b92ffa990dc57d8a969a98e3ca4e25ba39cbb2.zip
OFED user-space import and update for use with Linux-4.9 compatible RDMA
kernel APIs. List of sources used: 1) rdma-core was cloned from "https://github.com/linux-rdma/rdma-core.git" Top commit d65138ef93af30b3ea249f3a84aa6a24ba7f8a75 2) OpenSM was cloned from git://git.openfabrics.org/~halr/opensm.git Top commit 85f841cf209f791c89a075048a907020e924528d 3) libibmad was cloned from "git://git.openfabrics.org/~iraweiny/libibmad.git" Tag 1.3.13 with some additional patches from Mellanox. 4) infiniband-diags was cloned from "git://git.openfabrics.org/~iraweiny/infiniband-diags.git" Tag 1.6.7 with some additional patches from Mellanox. Added the required Makefiles for building and installing. Sponsored by: Mellanox Technologies
Notes
Notes: svn path=/projects/bsd_rdma_4_9/; revision=321936
Diffstat (limited to 'contrib/ofed/infiniband-diags')
-rw-r--r--contrib/ofed/infiniband-diags/build/Makefile29
-rw-r--r--contrib/ofed/infiniband-diags/build/Makefile.inc16
-rw-r--r--contrib/ofed/infiniband-diags/build/dump_fts/Makefile12
-rw-r--r--contrib/ofed/infiniband-diags/build/ibaddr/Makefile7
-rw-r--r--contrib/ofed/infiniband-diags/build/ibcacheedit/Makefile12
-rw-r--r--contrib/ofed/infiniband-diags/build/ibccconfig/Makefile7
-rw-r--r--contrib/ofed/infiniband-diags/build/ibccquery/Makefile7
-rw-r--r--contrib/ofed/infiniband-diags/build/iblinkinfo/Makefile12
-rw-r--r--contrib/ofed/infiniband-diags/build/ibmirror/Makefile7
-rw-r--r--contrib/ofed/infiniband-diags/build/ibnetdiscover/Makefile12
-rw-r--r--contrib/ofed/infiniband-diags/build/ibping/Makefile7
-rw-r--r--contrib/ofed/infiniband-diags/build/ibportstate/Makefile7
-rw-r--r--contrib/ofed/infiniband-diags/build/ibqueryerrors/Makefile12
-rw-r--r--contrib/ofed/infiniband-diags/build/ibroute/Makefile7
-rw-r--r--contrib/ofed/infiniband-diags/build/ibstat/Makefile7
-rw-r--r--contrib/ofed/infiniband-diags/build/ibsysstat/Makefile7
-rw-r--r--contrib/ofed/infiniband-diags/build/ibtracert/Makefile7
-rw-r--r--contrib/ofed/infiniband-diags/build/perfquery/Makefile7
-rw-r--r--contrib/ofed/infiniband-diags/build/saquery/Makefile7
-rw-r--r--contrib/ofed/infiniband-diags/build/sminfo/Makefile7
-rw-r--r--contrib/ofed/infiniband-diags/build/smpdump/Makefile7
-rw-r--r--contrib/ofed/infiniband-diags/build/smpquery/Makefile7
-rw-r--r--contrib/ofed/infiniband-diags/build/vendstat/Makefile7
-rw-r--r--contrib/ofed/infiniband-diags/config.h125
-rw-r--r--contrib/ofed/infiniband-diags/man/check_lft_balance.868
-rw-r--r--contrib/ofed/infiniband-diags/man/dump_fts.8235
-rw-r--r--contrib/ofed/infiniband-diags/man/ibaddr.8214
-rw-r--r--contrib/ofed/infiniband-diags/man/ibcacheedit.880
-rw-r--r--contrib/ofed/infiniband-diags/man/ibccconfig.8198
-rw-r--r--contrib/ofed/infiniband-diags/man/ibccquery.8194
-rw-r--r--contrib/ofed/infiniband-diags/man/ibfindnodesusing.8127
-rw-r--r--contrib/ofed/infiniband-diags/man/ibhosts.8184
-rw-r--r--contrib/ofed/infiniband-diags/man/ibidsverify.880
-rw-r--r--contrib/ofed/infiniband-diags/man/iblinkinfo.8319
-rw-r--r--contrib/ofed/infiniband-diags/man/ibnetdiscover.8399
-rw-r--r--contrib/ofed/infiniband-diags/man/ibnodes.8176
-rw-r--r--contrib/ofed/infiniband-diags/man/ibping.8177
-rw-r--r--contrib/ofed/infiniband-diags/man/ibportstate.8259
-rw-r--r--contrib/ofed/infiniband-diags/man/ibqueryerrors.8339
-rw-r--r--contrib/ofed/infiniband-diags/man/ibroute.8291
-rw-r--r--contrib/ofed/infiniband-diags/man/ibrouters.8184
-rw-r--r--contrib/ofed/infiniband-diags/man/ibstat.8118
-rw-r--r--contrib/ofed/infiniband-diags/man/ibstatus.873
-rw-r--r--contrib/ofed/infiniband-diags/man/ibswitches.8184
-rw-r--r--contrib/ofed/infiniband-diags/man/ibsysstat.8188
-rw-r--r--contrib/ofed/infiniband-diags/man/ibtracert.8268
-rw-r--r--contrib/ofed/infiniband-diags/man/infiniband-diags.8452
-rw-r--r--contrib/ofed/infiniband-diags/man/perfquery.8291
-rw-r--r--contrib/ofed/infiniband-diags/man/saquery.8380
-rw-r--r--contrib/ofed/infiniband-diags/man/sminfo.8215
-rw-r--r--contrib/ofed/infiniband-diags/man/smpdump.8207
-rw-r--r--contrib/ofed/infiniband-diags/man/smpquery.8310
-rw-r--r--contrib/ofed/infiniband-diags/man/vendstat.8221
-rw-r--r--contrib/ofed/infiniband-diags/src/dump_fts.c497
-rw-r--r--contrib/ofed/infiniband-diags/src/ibaddr.c168
-rw-r--r--contrib/ofed/infiniband-diags/src/ibcacheedit.c356
-rw-r--r--contrib/ofed/infiniband-diags/src/ibccconfig.c639
-rw-r--r--contrib/ofed/infiniband-diags/src/ibccquery.c427
-rw-r--r--contrib/ofed/infiniband-diags/src/ibdiag_common.c940
-rw-r--r--contrib/ofed/infiniband-diags/src/ibdiag_common.h178
-rw-r--r--contrib/ofed/infiniband-diags/src/ibdiag_sa.c256
-rw-r--r--contrib/ofed/infiniband-diags/src/ibdiag_sa.h94
-rw-r--r--contrib/ofed/infiniband-diags/src/ibdiag_version.h39
-rw-r--r--contrib/ofed/infiniband-diags/src/iblinkinfo.c768
-rw-r--r--contrib/ofed/infiniband-diags/src/ibmirror.c538
-rw-r--r--contrib/ofed/infiniband-diags/src/ibnetdiscover.c1157
-rw-r--r--contrib/ofed/infiniband-diags/src/ibping.c286
-rw-r--r--contrib/ofed/infiniband-diags/src/ibportstate.c767
-rw-r--r--contrib/ofed/infiniband-diags/src/ibqueryerrors.c1126
-rw-r--r--contrib/ofed/infiniband-diags/src/ibroute.c488
-rw-r--r--contrib/ofed/infiniband-diags/src/ibsendtrap.c278
-rw-r--r--contrib/ofed/infiniband-diags/src/ibstat.c335
-rw-r--r--contrib/ofed/infiniband-diags/src/ibsysstat.c367
-rw-r--r--contrib/ofed/infiniband-diags/src/ibtracert.c881
-rw-r--r--contrib/ofed/infiniband-diags/src/mcm_rereg_test.c399
-rw-r--r--contrib/ofed/infiniband-diags/src/perfquery.c1122
-rw-r--r--contrib/ofed/infiniband-diags/src/rdma-ndd.c433
-rw-r--r--contrib/ofed/infiniband-diags/src/saquery.c1984
-rw-r--r--contrib/ofed/infiniband-diags/src/sminfo.c162
-rw-r--r--contrib/ofed/infiniband-diags/src/smpdump.c318
-rw-r--r--contrib/ofed/infiniband-diags/src/smpquery.c509
-rw-r--r--contrib/ofed/infiniband-diags/src/vendstat.c552
82 files changed, 22837 insertions, 0 deletions
diff --git a/contrib/ofed/infiniband-diags/build/Makefile b/contrib/ofed/infiniband-diags/build/Makefile
new file mode 100644
index 000000000000..8ad5f3bea7cc
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/build/Makefile
@@ -0,0 +1,29 @@
+# $FreeBSD$
+
+SUBDIR= \
+dump_fts \
+ibaddr \
+ibcacheedit \
+ibccconfig \
+ibccquery \
+iblinkinfo \
+ibmirror \
+ibnetdiscover \
+ibping \
+ibportstate \
+ibqueryerrors \
+ibroute \
+ibstat \
+ibsysstat \
+ibtracert \
+perfquery \
+saquery \
+sminfo \
+smpdump \
+smpquery \
+vendstat
+
+SUBDIR_PARALLEL=
+
+.include <bsd.subdir.mk>
+
diff --git a/contrib/ofed/infiniband-diags/build/Makefile.inc b/contrib/ofed/infiniband-diags/build/Makefile.inc
new file mode 100644
index 000000000000..da56d0fcb4ba
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/build/Makefile.inc
@@ -0,0 +1,16 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../src ${.CURDIR}/../../man
+
+BINDIR?= /usr/bin
+SRCS+= ibdiag_common.c ibdiag_sa.c
+CFLAGS+= -I${INCLUDEDIR}/infiniband
+CFLAGS+= -DHAVE_CONFIG_H=1
+CFLAGS+= -I${.CURDIR}/../../
+CFLAGS+= -I${.CURDIR}/../../src
+.if defined(TESTBUILD)
+LDFLAGS+= -losmcomp -libmad -libumad
+.else
+LIBADD+= osmcomp ibmad ibumad
+.endif
+
diff --git a/contrib/ofed/infiniband-diags/build/dump_fts/Makefile b/contrib/ofed/infiniband-diags/build/dump_fts/Makefile
new file mode 100644
index 000000000000..aac67beab18b
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/build/dump_fts/Makefile
@@ -0,0 +1,12 @@
+# $FreeBSD$
+
+PROG= dump_fts
+SRCS= dump_fts.c
+.if defined(TESTBUILD)
+LDFLAGS= -libnetdisc
+.else
+LIBADD= ibnetdisc
+.endif
+MAN= dump_fts.8
+
+.include <bsd.prog.mk>
diff --git a/contrib/ofed/infiniband-diags/build/ibaddr/Makefile b/contrib/ofed/infiniband-diags/build/ibaddr/Makefile
new file mode 100644
index 000000000000..7aab4c2e310d
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/build/ibaddr/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+PROG= ibaddr
+SRCS= ibaddr.c
+MAN= ibaddr.8
+
+.include <bsd.prog.mk>
diff --git a/contrib/ofed/infiniband-diags/build/ibcacheedit/Makefile b/contrib/ofed/infiniband-diags/build/ibcacheedit/Makefile
new file mode 100644
index 000000000000..f686a151da31
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/build/ibcacheedit/Makefile
@@ -0,0 +1,12 @@
+# $FreeBSD$
+
+PROG= ibcacheedit
+SRCS= ibcacheedit.c
+.if defined(TESTBUILD)
+LDFLAGS= -libnetdisc
+.else
+LIBADD= ibnetdisc
+.endif
+MAN= ibcacheedit.8
+
+.include <bsd.prog.mk>
diff --git a/contrib/ofed/infiniband-diags/build/ibccconfig/Makefile b/contrib/ofed/infiniband-diags/build/ibccconfig/Makefile
new file mode 100644
index 000000000000..cfee9bf0eab8
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/build/ibccconfig/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+PROG= ibccconfig
+SRCS= ibccconfig.c
+MAN= ibccconfig.8
+
+.include <bsd.prog.mk>
diff --git a/contrib/ofed/infiniband-diags/build/ibccquery/Makefile b/contrib/ofed/infiniband-diags/build/ibccquery/Makefile
new file mode 100644
index 000000000000..7d278b1978da
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/build/ibccquery/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+PROG= ibccquery
+SRCS= ibccquery.c
+MAN= ibccquery.8
+
+.include <bsd.prog.mk>
diff --git a/contrib/ofed/infiniband-diags/build/iblinkinfo/Makefile b/contrib/ofed/infiniband-diags/build/iblinkinfo/Makefile
new file mode 100644
index 000000000000..cc0e5f086142
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/build/iblinkinfo/Makefile
@@ -0,0 +1,12 @@
+# $FreeBSD$
+
+PROG= iblinkinfo
+SRCS= iblinkinfo.c
+.if defined(TESTBUILD)
+LDFLAGS= -libnetdisc
+.else
+LIBADD= ibnetdisc
+.endif
+MAN= iblinkinfo.8
+
+.include <bsd.prog.mk>
diff --git a/contrib/ofed/infiniband-diags/build/ibmirror/Makefile b/contrib/ofed/infiniband-diags/build/ibmirror/Makefile
new file mode 100644
index 000000000000..4684c2058855
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/build/ibmirror/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+PROG= ibmirror
+SRCS= ibmirror.c
+MAN=
+
+.include <bsd.prog.mk>
diff --git a/contrib/ofed/infiniband-diags/build/ibnetdiscover/Makefile b/contrib/ofed/infiniband-diags/build/ibnetdiscover/Makefile
new file mode 100644
index 000000000000..847e4f7a8ca5
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/build/ibnetdiscover/Makefile
@@ -0,0 +1,12 @@
+# $FreeBSD$
+
+PROG= ibnetdiscover
+SRCS= ibnetdiscover.c
+.if defined(TESTBUILD)
+LDFLAGS= -libnetdisc
+.else
+LIBADD= ibnetdisc
+.endif
+MAN= ibnetdiscover.8
+
+.include <bsd.prog.mk>
diff --git a/contrib/ofed/infiniband-diags/build/ibping/Makefile b/contrib/ofed/infiniband-diags/build/ibping/Makefile
new file mode 100644
index 000000000000..e573f780153a
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/build/ibping/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+PROG= ibping
+SRCS= ibping.c
+MAN= ibping.8
+
+.include <bsd.prog.mk>
diff --git a/contrib/ofed/infiniband-diags/build/ibportstate/Makefile b/contrib/ofed/infiniband-diags/build/ibportstate/Makefile
new file mode 100644
index 000000000000..98dc34ca5fe7
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/build/ibportstate/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+PROG= ibportstate
+SRCS= ibportstate.c
+MAN= ibportstate.8
+
+.include <bsd.prog.mk>
diff --git a/contrib/ofed/infiniband-diags/build/ibqueryerrors/Makefile b/contrib/ofed/infiniband-diags/build/ibqueryerrors/Makefile
new file mode 100644
index 000000000000..5aa97cc4de2c
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/build/ibqueryerrors/Makefile
@@ -0,0 +1,12 @@
+# $FreeBSD$
+
+PROG= ibqueryerrors
+SRCS= ibqueryerrors.c
+.if defined(TESTBUILD)
+LDFLAGS= -libnetdisc
+.else
+LIBADD= ibnetdisc
+.endif
+MAN= ibqueryerrors.8
+
+.include <bsd.prog.mk>
diff --git a/contrib/ofed/infiniband-diags/build/ibroute/Makefile b/contrib/ofed/infiniband-diags/build/ibroute/Makefile
new file mode 100644
index 000000000000..1914fca8abe1
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/build/ibroute/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+PROG= ibroute
+SRCS= ibroute.c
+MAN= ibroute.8
+
+.include <bsd.prog.mk>
diff --git a/contrib/ofed/infiniband-diags/build/ibstat/Makefile b/contrib/ofed/infiniband-diags/build/ibstat/Makefile
new file mode 100644
index 000000000000..812cd03d623b
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/build/ibstat/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+PROG= ibstat
+SRCS= ibstat.c
+MAN= ibstat.8
+
+.include <bsd.prog.mk>
diff --git a/contrib/ofed/infiniband-diags/build/ibsysstat/Makefile b/contrib/ofed/infiniband-diags/build/ibsysstat/Makefile
new file mode 100644
index 000000000000..b2f0ab7698e7
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/build/ibsysstat/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+PROG= ibsysstat
+SRCS= ibsysstat.c
+MAN= ibsysstat.8
+
+.include <bsd.prog.mk>
diff --git a/contrib/ofed/infiniband-diags/build/ibtracert/Makefile b/contrib/ofed/infiniband-diags/build/ibtracert/Makefile
new file mode 100644
index 000000000000..ea6d66a5dde5
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/build/ibtracert/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+PROG= ibtracert
+SRCS= ibtracert.c
+MAN= ibtracert.8
+
+.include <bsd.prog.mk>
diff --git a/contrib/ofed/infiniband-diags/build/perfquery/Makefile b/contrib/ofed/infiniband-diags/build/perfquery/Makefile
new file mode 100644
index 000000000000..3b4cb536717f
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/build/perfquery/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+PROG= perfquery
+SRCS= perfquery.c
+MAN= perfquery.8
+
+.include <bsd.prog.mk>
diff --git a/contrib/ofed/infiniband-diags/build/saquery/Makefile b/contrib/ofed/infiniband-diags/build/saquery/Makefile
new file mode 100644
index 000000000000..f330cd3c5046
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/build/saquery/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+PROG= saquery
+SRCS= saquery.c
+MAN= saquery.8
+
+.include <bsd.prog.mk>
diff --git a/contrib/ofed/infiniband-diags/build/sminfo/Makefile b/contrib/ofed/infiniband-diags/build/sminfo/Makefile
new file mode 100644
index 000000000000..b83d759668f3
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/build/sminfo/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+PROG= sminfo
+SRCS= sminfo.c
+MAN= sminfo.8
+
+.include <bsd.prog.mk>
diff --git a/contrib/ofed/infiniband-diags/build/smpdump/Makefile b/contrib/ofed/infiniband-diags/build/smpdump/Makefile
new file mode 100644
index 000000000000..ae1c680e2443
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/build/smpdump/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+PROG= smpdump
+SRCS= smpdump.c
+MAN= smpdump.8
+
+.include <bsd.prog.mk>
diff --git a/contrib/ofed/infiniband-diags/build/smpquery/Makefile b/contrib/ofed/infiniband-diags/build/smpquery/Makefile
new file mode 100644
index 000000000000..4654ce400d44
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/build/smpquery/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+PROG= smpquery
+SRCS= smpquery.c
+MAN= smpquery.8
+
+.include <bsd.prog.mk>
diff --git a/contrib/ofed/infiniband-diags/build/vendstat/Makefile b/contrib/ofed/infiniband-diags/build/vendstat/Makefile
new file mode 100644
index 000000000000..b548537bff8d
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/build/vendstat/Makefile
@@ -0,0 +1,7 @@
+# $FreeBSD$
+
+PROG= vendstat
+SRCS= vendstat.c
+MAN= vendstat.8
+
+.include <bsd.prog.mk>
diff --git a/contrib/ofed/infiniband-diags/config.h b/contrib/ofed/infiniband-diags/config.h
new file mode 100644
index 000000000000..d203120beac2
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/config.h
@@ -0,0 +1,125 @@
+/* config.h. Generated from config.h.in by configure. */
+/* config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if you don't have `vprintf' but do have `_doprnt.' */
+/* #undef HAVE_DOPRNT */
+
+/* Define to 1 if you have the <fcntl.h> header file. */
+#define HAVE_FCNTL_H 1
+
+/* Define to 1 to indicate GLIB support */
+/* #undef HAVE_GLIB */
+
+/* Define if IB_PC_QP1_DROP_F exists in mad.h enum MAD_FIELDS. */
+#define HAVE_IB_PC_QP1_DROP_F 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the `ibmad' library (-libmad). */
+#define HAVE_LIBIBMAD 1
+
+/* Define to 1 if you have the `ibumad' library (-libumad). */
+#define HAVE_LIBIBUMAD 1
+
+/* Define to 1 if you have the `osmcomp' library (-losmcomp). */
+#define HAVE_LIBOSMCOMP 1
+
+/* Define to 1 if you have the `udev' library (-ludev). */
+/* #undef HAVE_LIBUDEV */
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `memset' function. */
+#define HAVE_MEMSET 1
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#define HAVE_NETINET_IN_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strchr' function. */
+#define HAVE_STRCHR 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strrchr' function. */
+#define HAVE_STRRCHR 1
+
+/* Define to 1 if you have the `strtol' function. */
+#define HAVE_STRTOL 1
+
+/* Define to 1 if you have the `strtoul' function. */
+#define HAVE_STRTOUL 1
+
+/* Define to 1 if you have the `strtoull' function. */
+#define HAVE_STRTOULL 1
+
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#define HAVE_SYS_IOCTL_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the `udev_get_sys_path' function. */
+/* #undef HAVE_UDEV_GET_SYS_PATH */
+
+/* Define to 1 if struct umad_port has link_layer member */
+#define HAVE_UMAD_PORT_LINK_LAYER 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to 1 if you have the `vprintf' function. */
+#define HAVE_VPRINTF 1
+
+/* Define the path to configurations */
+#define IBDIAG_CONFIG_PATH "/etc/infiniband-diags"
+
+/* Define to the sub-directory where libtool stores uninstalled libraries. */
+#define LT_OBJDIR ".libs/"
+
+/* Name of package */
+#define PACKAGE "infiniband-diags"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "linux-rdma@vger.kernel.org"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "infiniband-diags"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "infiniband-diags 1.6.7"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "infiniband-diags"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "1.6.7"
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Version number of package */
+#define VERSION "1.6.7"
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
diff --git a/contrib/ofed/infiniband-diags/man/check_lft_balance.8 b/contrib/ofed/infiniband-diags/man/check_lft_balance.8
new file mode 100644
index 000000000000..af0580f3665e
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/man/check_lft_balance.8
@@ -0,0 +1,68 @@
+.\" Man page generated from reStructuredText.
+.
+.TH CHECK_LFT_BALANCE 8 "" "" "Open IB Diagnostics"
+.SH NAME
+CHECK_LFT_BALANCE \-
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.SH CHECK INFINIBAND UNICAST FORWARDING TABLES BALANCE
+.SS SYNOPSIS
+.sp
+check_lft_balance.sh [\-hRv]
+.SS DESCRIPTION
+.sp
+check_lft_balance.sh is a script which checks for balancing in Infiniband
+unicast forwarding tables. It analyzes the output of
+\fBdump_lfts(8)\fP and \fBiblinkinfo(8)\fP
+.SS OPTIONS
+.INDENT 0.0
+.TP
+.B \fB\-h\fP
+show help
+.TP
+.B \fB\-R\fP
+Recalculate dump_lfts information, ie do not use the cached
+information. This option is slower but should be used if the diag
+tools have not been used for some time or if there are other reasons to
+believe that the fabric has changed.
+.TP
+.B \fB\-v\fP
+verbose output
+.UNINDENT
+.SS SEE ALSO
+.sp
+\fBdump_lfts(8)\fP
+\fBiblinkinfo(8)\fP
+.SS AUTHORS
+.INDENT 0.0
+.TP
+.B Albert Chu
+< \fI\%chu11@llnl.gov\fP >
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/contrib/ofed/infiniband-diags/man/dump_fts.8 b/contrib/ofed/infiniband-diags/man/dump_fts.8
new file mode 100644
index 000000000000..ef77502e3696
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/man/dump_fts.8
@@ -0,0 +1,235 @@
+.\" Man page generated from reStructuredText.
+.
+.TH DUMP_FTS 8 "" "" "OpenIB Diagnostics"
+.SH NAME
+DUMP_FTS \- dump InfiniBand forwarding tables
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.SH SYNOPSIS
+.sp
+dump_fts [options] [<startlid> [<endlid>]]
+.SH DESCRIPTION
+.sp
+dump_fts is similar to ibroute but dumps tables for every switch found in an
+ibnetdiscover scan of the subnet.
+.sp
+The dump file format is compatible with loading into OpenSM using
+the \-R file \-U /path/to/dump\-file syntax.
+.SH OPTIONS
+.INDENT 0.0
+.TP
+.B \fB\-a, \-\-all\fP
+show all lids in range, even invalid entries
+.TP
+.B \fB\-n, \-\-no_dests\fP
+do not try to resolve destinations
+.TP
+.B \fB\-M, \-\-Multicast\fP
+show multicast forwarding tables
+In this case, the range parameters are specifying the mlid range.
+.UNINDENT
+.SS Port Selection flags
+.\" Define the common option -C
+.
+.sp
+\fB\-C, \-\-Ca <ca_name>\fP use the specified ca_name.
+.\" Define the common option -P
+.
+.sp
+\fB\-P, \-\-Port <ca_port>\fP use the specified ca_port.
+.\" Explanation of local port selection
+.
+.SS Local port Selection
+.sp
+Multiple port/Multiple CA support: when no IB device or port is specified
+(see the "local umad parameters" below), the libibumad library
+selects the port to use by the following criteria:
+.INDENT 0.0
+.INDENT 3.5
+.INDENT 0.0
+.IP 1. 3
+the first port that is ACTIVE.
+.IP 2. 3
+if not found, the first port that is UP (physical link up).
+.UNINDENT
+.sp
+If a port and/or CA name is specified, the libibumad library attempts
+to fulfill the user request, and will fail if it is not possible.
+.sp
+For example:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+ibaddr # use the first port (criteria #1 above)
+ibaddr \-C mthca1 # pick the best port from "mthca1" only.
+ibaddr \-P 2 # use the second (active/up) port from the first available IB device.
+ibaddr \-C mthca0 \-P 2 # use the specified port only.
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS Debugging flags
+.\" Define the common option -d
+.
+.INDENT 0.0
+.TP
+.B \-d
+raise the IB debugging level.
+May be used several times (\-ddd or \-d \-d \-d).
+.UNINDENT
+.\" Define the common option -e
+.
+.INDENT 0.0
+.TP
+.B \-e
+show send and receive errors (timeouts and others)
+.UNINDENT
+.\" Define the common option -h
+.
+.sp
+\fB\-h, \-\-help\fP show the usage message
+.\" Define the common option -v
+.
+.INDENT 0.0
+.TP
+.B \fB\-v, \-\-verbose\fP
+increase the application verbosity level.
+May be used several times (\-vv or \-v \-v \-v)
+.UNINDENT
+.\" Define the common option -V
+.
+.sp
+\fB\-V, \-\-version\fP show the version info.
+.SS Configuration flags
+.\" Define the common option -t
+.
+.sp
+\fB\-t, \-\-timeout <timeout_ms>\fP override the default timeout for the solicited mads.
+.\" Define the common option -y
+.
+.INDENT 0.0
+.TP
+.B \fB\-y, \-\-m_key <key>\fP
+use the specified M_key for requests. If non\-numeric value (like \(aqx\(aq)
+is specified then a value will be prompted for.
+.UNINDENT
+.\" Define the common option --node-name-map
+.
+.sp
+\fB\-\-node\-name\-map <node\-name\-map>\fP Specify a node name map.
+.INDENT 0.0
+.INDENT 3.5
+This file maps GUIDs to more user friendly names. See FILES section.
+.UNINDENT
+.UNINDENT
+.\" Define the common option -z
+.
+.sp
+\fB\-\-config, \-z <config_file>\fP Specify alternate config file.
+.INDENT 0.0
+.INDENT 3.5
+Default: /etc/infiniband-diags/ibdiag.conf
+.UNINDENT
+.UNINDENT
+.SH FILES
+.\" Common text for the config file
+.
+.SS CONFIG FILE
+.sp
+/etc/infiniband-diags/ibdiag.conf
+.sp
+A global config file is provided to set some of the common options for all
+tools. See supplied config file for details.
+.\" Common text to describe the node name map file.
+.
+.SS NODE NAME MAP FILE FORMAT
+.sp
+The node name map is used to specify user friendly names for nodes in the
+output. GUIDs are used to perform the lookup.
+.sp
+This functionality is provided by the opensm\-libs package. See \fBopensm(8)\fP
+for the file location for your installation.
+.sp
+\fBGenerically:\fP
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+# comment
+<guid> "<name>"
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+\fBExample:\fP
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+# IB1
+# Line cards
+0x0008f104003f125c "IB1 (Rack 11 slot 1 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f125d "IB1 (Rack 11 slot 1 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f10d2 "IB1 (Rack 11 slot 2 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f10d3 "IB1 (Rack 11 slot 2 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f10bf "IB1 (Rack 11 slot 12 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+
+# Spines
+0x0008f10400400e2d "IB1 (Rack 11 spine 1 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e2e "IB1 (Rack 11 spine 1 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e2f "IB1 (Rack 11 spine 1 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e31 "IB1 (Rack 11 spine 2 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e32 "IB1 (Rack 11 spine 2 ) ISR9288 Voltaire sFB\-12D"
+
+# GUID Node Name
+0x0008f10400411a08 "SW1 (Rack 3) ISR9024 Voltaire 9024D"
+0x0008f10400411a28 "SW2 (Rack 3) ISR9024 Voltaire 9024D"
+0x0008f10400411a34 "SW3 (Rack 3) ISR9024 Voltaire 9024D"
+0x0008f104004119d0 "SW4 (Rack 3) ISR9024 Voltaire 9024D"
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SH SEE ALSO
+.sp
+\fBdump_lfts(8), dump_mfts(8), ibroute(8), ibswitches(8), opensm(8)\fP
+.SH AUTHORS
+.INDENT 0.0
+.TP
+.B Ira Weiny
+< \fI\%ira.weiny@intel.com\fP >
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/contrib/ofed/infiniband-diags/man/ibaddr.8 b/contrib/ofed/infiniband-diags/man/ibaddr.8
new file mode 100644
index 000000000000..2b476da33d9b
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/man/ibaddr.8
@@ -0,0 +1,214 @@
+.\" Man page generated from reStructuredText.
+.
+.TH IBADDR 8 "" "" "OpenIB Diagnostics"
+.SH NAME
+IBADDR \- query InfiniBand address(es)
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.SH SYNOPSIS
+.sp
+ibaddr [options]
+.SH DESCRIPTION
+.sp
+Display the lid (and range) as well as the GID address of the
+port specified (by DR path, lid, or GUID) or the local port by default.
+.sp
+Note: this utility can be used as simple address resolver.
+.SH OPTIONS
+.sp
+\fB\-\-gid_show, \-g\fP
+show gid address only
+.sp
+\fB\-\-lid_show, \-l\fP
+show lid range only
+.sp
+\fB\-\-Lid_show, \-L\fP
+show lid range (in decimal) only
+.SS Addressing Flags
+.\" Define the common option -D for Directed routes
+.
+.sp
+\fB\-D, \-\-Direct\fP The address specified is a directed route
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+Examples:
+ [options] \-D [options] "0" # self port
+ [options] \-D [options] "0,1,2,1,4" # out via port 1, then 2, ...
+
+ (Note the second number in the path specified must match the port being
+ used. This can be specified using the port selection flag \(aq\-P\(aq or the
+ port found through the automatic selection process.)
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.\" Define the common option -G
+.
+.sp
+\fB\-G, \-\-Guid\fP The address specified is a Port GUID
+.\" Define the common option -s
+.
+.sp
+\fB\-s, \-\-sm_port <smlid>\fP use \(aqsmlid\(aq as the target lid for SA queries.
+.SS Debugging flags
+.\" Define the common option -d
+.
+.INDENT 0.0
+.TP
+.B \-d
+raise the IB debugging level.
+May be used several times (\-ddd or \-d \-d \-d).
+.UNINDENT
+.\" Define the common option -e
+.
+.INDENT 0.0
+.TP
+.B \-e
+show send and receive errors (timeouts and others)
+.UNINDENT
+.\" Define the common option -h
+.
+.sp
+\fB\-h, \-\-help\fP show the usage message
+.\" Define the common option -v
+.
+.INDENT 0.0
+.TP
+.B \fB\-v, \-\-verbose\fP
+increase the application verbosity level.
+May be used several times (\-vv or \-v \-v \-v)
+.UNINDENT
+.\" Define the common option -V
+.
+.sp
+\fB\-V, \-\-version\fP show the version info.
+.SS Port Selection flags
+.\" Define the common option -C
+.
+.sp
+\fB\-C, \-\-Ca <ca_name>\fP use the specified ca_name.
+.\" Define the common option -P
+.
+.sp
+\fB\-P, \-\-Port <ca_port>\fP use the specified ca_port.
+.\" Explanation of local port selection
+.
+.SS Local port Selection
+.sp
+Multiple port/Multiple CA support: when no IB device or port is specified
+(see the "local umad parameters" below), the libibumad library
+selects the port to use by the following criteria:
+.INDENT 0.0
+.INDENT 3.5
+.INDENT 0.0
+.IP 1. 3
+the first port that is ACTIVE.
+.IP 2. 3
+if not found, the first port that is UP (physical link up).
+.UNINDENT
+.sp
+If a port and/or CA name is specified, the libibumad library attempts
+to fulfill the user request, and will fail if it is not possible.
+.sp
+For example:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+ibaddr # use the first port (criteria #1 above)
+ibaddr \-C mthca1 # pick the best port from "mthca1" only.
+ibaddr \-P 2 # use the second (active/up) port from the first available IB device.
+ibaddr \-C mthca0 \-P 2 # use the specified port only.
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS Configuration flags
+.\" Define the common option -y
+.
+.INDENT 0.0
+.TP
+.B \fB\-y, \-\-m_key <key>\fP
+use the specified M_key for requests. If non\-numeric value (like \(aqx\(aq)
+is specified then a value will be prompted for.
+.UNINDENT
+.\" Define the common option -t
+.
+.sp
+\fB\-t, \-\-timeout <timeout_ms>\fP override the default timeout for the solicited mads.
+.\" Define the common option -z
+.
+.sp
+\fB\-\-config, \-z <config_file>\fP Specify alternate config file.
+.INDENT 0.0
+.INDENT 3.5
+Default: /etc/infiniband-diags/ibdiag.conf
+.UNINDENT
+.UNINDENT
+.SH FILES
+.\" Common text for the config file
+.
+.SS CONFIG FILE
+.sp
+/etc/infiniband-diags/ibdiag.conf
+.sp
+A global config file is provided to set some of the common options for all
+tools. See supplied config file for details.
+.SH EXAMPLES
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+ibaddr # local port\e\(aqs address
+ibaddr 32 # show lid range and gid of lid 32
+ibaddr \-G 0x8f1040023 # same but using guid address
+ibaddr \-l 32 # show lid range only
+ibaddr \-L 32 # show decimal lid range only
+ibaddr \-g 32 # show gid address only
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SH SEE ALSO
+.sp
+\fBibroute (8), ibtracert (8)\fP
+.SH AUTHOR
+.INDENT 0.0
+.TP
+.B Hal Rosenstock
+< \fI\%halr@voltaire.com\fP >
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/contrib/ofed/infiniband-diags/man/ibcacheedit.8 b/contrib/ofed/infiniband-diags/man/ibcacheedit.8
new file mode 100644
index 000000000000..7e3830ad288f
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/man/ibcacheedit.8
@@ -0,0 +1,80 @@
+.\" Man page generated from reStructuredText.
+.
+.TH IBCACHEEDIT 8 "" "" "Open IB Diagnostics"
+.SH NAME
+IBCACHEEDIT \-
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.SH EDIT AN IBNETDISCOVER CACHE
+.SS SYNOPSIS
+.sp
+ibcacheedit [options] <orig.cache> <new.cache>
+.SS DESCRIPTION
+.sp
+ibcacheedit allows users to edit an ibnetdiscover cache created through the
+\fB\-\-cache\fP option in \fBibnetdiscover(8)\fP .
+.SS OPTIONS
+.INDENT 0.0
+.TP
+.B \fB\-\-switchguid BEFOREGUID:AFTERGUID\fP
+Specify a switchguid that should be changed. The before and after guid
+should be separated by a colon. On switches, port guids are identical
+to the switch guid, so port guids will be adjusted as well on switches.
+.TP
+.B \fB\-\-caguid BEFOREGUID:AFTERGUID\fP
+Specify a caguid that should be changed. The before and after guid
+should be separated by a colon.
+.TP
+.B \fB\-\-sysimgguid BEFOREGUID:AFTERGUID\fP
+Specify a sysimgguid that should be changed. The before and after guid
+should be spearated by a colon.
+.TP
+.B \fB\-\-portguid NODEGUID:BEFOREGUID:AFTERGUID\fP
+Specify a portguid that should be changed. The nodeguid of the port
+(e.g. switchguid or caguid) should be specified first, followed by a
+colon, the before port guid, another colon, then the after port guid.
+On switches, port guids are identical to the switch guid, so the switch
+guid will be adjusted as well on switches.
+.UNINDENT
+.SS Debugging flags
+.\" Define the common option -h
+.
+.sp
+\fB\-h, \-\-help\fP show the usage message
+.\" Define the common option -V
+.
+.sp
+\fB\-V, \-\-version\fP show the version info.
+.SS AUTHORS
+.INDENT 0.0
+.TP
+.B Albert Chu
+< \fI\%chu11@llnl.gov\fP >
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/contrib/ofed/infiniband-diags/man/ibccconfig.8 b/contrib/ofed/infiniband-diags/man/ibccconfig.8
new file mode 100644
index 000000000000..9d244f2fe95f
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/man/ibccconfig.8
@@ -0,0 +1,198 @@
+.\" Man page generated from reStructuredText.
+.
+.TH IBCCCONFIG 8 "" "" "OpenIB Diagnostics"
+.SH NAME
+IBCCCONFIG \- configure congestion control settings
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.SH SYNOPSIS
+.sp
+ibccconfig [common_options] [\-c cckey] [\-\-dgid gid] <op> <lid|guid> [port]
+.SH DESCRIPTION
+.sp
+\fBibccconfig\fP
+supports the configuration of congestion control settings on switches
+and HCAs.
+.sp
+\fBWARNING \-\- You should understand what you are doing before using this tool.
+Misuse of this tool could result in a broken fabric.\fP
+.SH OPTIONS
+.INDENT 0.0
+.TP
+.B Current supported operations and their parameters:
+CongestionKeyInfo (CK) <lid|guid> <cckey> <cckeyprotectbit> <cckeyleaseperiod> <cckeyviolations>
+SwitchCongestionSetting (SS) <lid|guid> <controlmap> <victimmask> <creditmask> <threshold> <packetsize> <csthreshold> <csreturndelay> <markingrate>
+SwitchPortCongestionSetting (SP) <lid|guid> <portnum> <valid> <control_type> <threshold> <packet_size> <cong_parm_marking_rate>
+CACongestionSetting (CS) <lid|guid> <port_control> <control_map> <ccti_timer> <ccti_increase> <trigger_threshold> <ccti_min>
+CongestionControlTable (CT) <lid|guid> <cctilimit> <index> <cctentry> <cctentry> ...
+.UNINDENT
+.sp
+\fB\-\-cckey, \-c, <cckey>\fP
+Specify a congestion control (CC) key. If none is specified, a key of 0 is used.
+.sp
+\fB\-\-dgid <dgid>\fP
+destination GID: use when GRH is required in packets (IPv6 format)
+.SS Debugging flags
+.\" Define the common option -d
+.
+.INDENT 0.0
+.TP
+.B \-d
+raise the IB debugging level.
+May be used several times (\-ddd or \-d \-d \-d).
+.UNINDENT
+.\" Define the common option -e
+.
+.INDENT 0.0
+.TP
+.B \-e
+show send and receive errors (timeouts and others)
+.UNINDENT
+.\" Define the common option -h
+.
+.sp
+\fB\-h, \-\-help\fP show the usage message
+.\" Define the common option -v
+.
+.INDENT 0.0
+.TP
+.B \fB\-v, \-\-verbose\fP
+increase the application verbosity level.
+May be used several times (\-vv or \-v \-v \-v)
+.UNINDENT
+.\" Define the common option -V
+.
+.sp
+\fB\-V, \-\-version\fP show the version info.
+.SS Addressing Flags
+.\" Define the common option -G
+.
+.sp
+\fB\-G, \-\-Guid\fP The address specified is a Port GUID
+.\" Define the common option -L
+.
+.sp
+\fB\-L, \-\-Lid\fP The address specified is a LID
+.\" Define the common option -s
+.
+.sp
+\fB\-s, \-\-sm_port <smlid>\fP use \(aqsmlid\(aq as the target lid for SA queries.
+.SS Port Selection flags
+.\" Define the common option -C
+.
+.sp
+\fB\-C, \-\-Ca <ca_name>\fP use the specified ca_name.
+.\" Define the common option -P
+.
+.sp
+\fB\-P, \-\-Port <ca_port>\fP use the specified ca_port.
+.\" Explanation of local port selection
+.
+.SS Local port Selection
+.sp
+Multiple port/Multiple CA support: when no IB device or port is specified
+(see the "local umad parameters" below), the libibumad library
+selects the port to use by the following criteria:
+.INDENT 0.0
+.INDENT 3.5
+.INDENT 0.0
+.IP 1. 3
+the first port that is ACTIVE.
+.IP 2. 3
+if not found, the first port that is UP (physical link up).
+.UNINDENT
+.sp
+If a port and/or CA name is specified, the libibumad library attempts
+to fulfill the user request, and will fail if it is not possible.
+.sp
+For example:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+ibaddr # use the first port (criteria #1 above)
+ibaddr \-C mthca1 # pick the best port from "mthca1" only.
+ibaddr \-P 2 # use the second (active/up) port from the first available IB device.
+ibaddr \-C mthca0 \-P 2 # use the specified port only.
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS Configuration flags
+.\" Define the common option -y
+.
+.INDENT 0.0
+.TP
+.B \fB\-y, \-\-m_key <key>\fP
+use the specified M_key for requests. If non\-numeric value (like \(aqx\(aq)
+is specified then a value will be prompted for.
+.UNINDENT
+.\" Define the common option -z
+.
+.sp
+\fB\-\-config, \-z <config_file>\fP Specify alternate config file.
+.INDENT 0.0
+.INDENT 3.5
+Default: /etc/infiniband-diags/ibdiag.conf
+.UNINDENT
+.UNINDENT
+.SH EXAMPLES
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+ibccconfig SwitchCongestionSetting 2 0x1F 0x1FFFFFFFFF 0x0 0xF 8 0 0:0 1 # Configure Switch Congestion Settings
+ibccconfig CACongestionSetting 1 0 0x3 150 1 0 0 # Configure CA Congestion Settings to SL 0 and SL 1
+ibccconfig CACongestionSetting 1 0 0x4 200 1 0 0 # Configure CA Congestion Settings to SL 2
+ibccconfig CongestionControlTable 1 63 0 0:0 0:1 ... # Configure first block of Congestion Control Table
+ibccconfig CongestionControlTable 1 127 0 0:64 0:65 ... # Configure second block of Congestion Control Table
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SH FILES
+.\" Common text for the config file
+.
+.SS CONFIG FILE
+.sp
+/etc/infiniband-diags/ibdiag.conf
+.sp
+A global config file is provided to set some of the common options for all
+tools. See supplied config file for details.
+.SH AUTHOR
+.INDENT 0.0
+.TP
+.B Albert Chu
+< \fI\%chu11@llnl.gov\fP >
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/contrib/ofed/infiniband-diags/man/ibccquery.8 b/contrib/ofed/infiniband-diags/man/ibccquery.8
new file mode 100644
index 000000000000..cae3f33a39e2
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/man/ibccquery.8
@@ -0,0 +1,194 @@
+.\" Man page generated from reStructuredText.
+.
+.TH IBCCQUERY 8 "" "" "OpenIB Diagnostics"
+.SH NAME
+IBCCQUERY \- query congestion control settings/info
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.SH SYNOPSIS
+.sp
+ibccquery [common_options] [\-c cckey] [\-\-dgid gid] <op> <lid|guid> [port]
+.SH DESCRIPTION
+.sp
+ibccquery support the querying of settings and other information related
+to congestion control.
+.SH OPTIONS
+.INDENT 0.0
+.TP
+.B Current supported operations and their parameters:
+CongestionInfo (CI) <addr>
+CongestionKeyInfo (CK) <addr>
+CongestionLog (CL) <addr>
+SwitchCongestionSetting (SS) <addr>
+SwitchPortCongestionSetting (SP) <addr> [<portnum>]
+CACongestionSetting (CS) <addr>
+CongestionControlTable (CT) <addr>
+Timestamp (TI) <addr>
+.UNINDENT
+.sp
+\fB\-\-cckey, \-c <cckey>\fP
+Specify a congestion control (CC) key. If none is specified, a key of 0 is used.
+\fB\-\-dgid <gid>\fP
+destination GID: use when GRH is required in packets (IPv6 format)
+.SS Debugging flags
+.\" Define the common option -d
+.
+.INDENT 0.0
+.TP
+.B \-d
+raise the IB debugging level.
+May be used several times (\-ddd or \-d \-d \-d).
+.UNINDENT
+.\" Define the common option -e
+.
+.INDENT 0.0
+.TP
+.B \-e
+show send and receive errors (timeouts and others)
+.UNINDENT
+.\" Define the common option -h
+.
+.sp
+\fB\-h, \-\-help\fP show the usage message
+.\" Define the common option -v
+.
+.INDENT 0.0
+.TP
+.B \fB\-v, \-\-verbose\fP
+increase the application verbosity level.
+May be used several times (\-vv or \-v \-v \-v)
+.UNINDENT
+.\" Define the common option -V
+.
+.sp
+\fB\-V, \-\-version\fP show the version info.
+.SS Addressing Flags
+.\" Define the common option -G
+.
+.sp
+\fB\-G, \-\-Guid\fP The address specified is a Port GUID
+.\" Define the common option -L
+.
+.sp
+\fB\-L, \-\-Lid\fP The address specified is a LID
+.\" Define the common option -s
+.
+.sp
+\fB\-s, \-\-sm_port <smlid>\fP use \(aqsmlid\(aq as the target lid for SA queries.
+.SS Port Selection flags
+.\" Define the common option -C
+.
+.sp
+\fB\-C, \-\-Ca <ca_name>\fP use the specified ca_name.
+.\" Define the common option -P
+.
+.sp
+\fB\-P, \-\-Port <ca_port>\fP use the specified ca_port.
+.\" Explanation of local port selection
+.
+.SS Local port Selection
+.sp
+Multiple port/Multiple CA support: when no IB device or port is specified
+(see the "local umad parameters" below), the libibumad library
+selects the port to use by the following criteria:
+.INDENT 0.0
+.INDENT 3.5
+.INDENT 0.0
+.IP 1. 3
+the first port that is ACTIVE.
+.IP 2. 3
+if not found, the first port that is UP (physical link up).
+.UNINDENT
+.sp
+If a port and/or CA name is specified, the libibumad library attempts
+to fulfill the user request, and will fail if it is not possible.
+.sp
+For example:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+ibaddr # use the first port (criteria #1 above)
+ibaddr \-C mthca1 # pick the best port from "mthca1" only.
+ibaddr \-P 2 # use the second (active/up) port from the first available IB device.
+ibaddr \-C mthca0 \-P 2 # use the specified port only.
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS Configuration flags
+.\" Define the common option -y
+.
+.INDENT 0.0
+.TP
+.B \fB\-y, \-\-m_key <key>\fP
+use the specified M_key for requests. If non\-numeric value (like \(aqx\(aq)
+is specified then a value will be prompted for.
+.UNINDENT
+.\" Define the common option -z
+.
+.sp
+\fB\-\-config, \-z <config_file>\fP Specify alternate config file.
+.INDENT 0.0
+.INDENT 3.5
+Default: /etc/infiniband-diags/ibdiag.conf
+.UNINDENT
+.UNINDENT
+.SH FILES
+.\" Common text for the config file
+.
+.SS CONFIG FILE
+.sp
+/etc/infiniband-diags/ibdiag.conf
+.sp
+A global config file is provided to set some of the common options for all
+tools. See supplied config file for details.
+.SH EXAMPLES
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+ibccquery CongestionInfo 3 # Congestion Info by lid
+ibccquery SwitchPortCongestionSetting 3 # Query all Switch Port Congestion Settings
+ibccquery SwitchPortCongestionSetting 3 1 # Query Switch Port Congestion Setting for port 1
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SH AUTHOR
+.INDENT 0.0
+.TP
+.B Albert Chu
+< \fI\%chu11@llnl.gov\fP >
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/contrib/ofed/infiniband-diags/man/ibfindnodesusing.8 b/contrib/ofed/infiniband-diags/man/ibfindnodesusing.8
new file mode 100644
index 000000000000..9ff6db8a8347
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/man/ibfindnodesusing.8
@@ -0,0 +1,127 @@
+.\" Man page generated from reStructuredText.
+.
+.TH IBFINDNODESUSING 8 "" "" "Open IB Diagnostics"
+.SH NAME
+IBFINDNODESUSING \-
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.SH FIND A LIST OF END NODES WHICH ARE ROUTED THROUGH THE SPECIFIED SWITCH AND PORT
+.SS SYNOPSIS
+.sp
+ibfindnodesusing.pl [options] <switch_guid|switch_name> <port>
+.SS DESCRIPTION
+.sp
+ibfindnodesusing.pl uses ibroute and detects the current nodes which are routed
+through both directions of the link specified. The link is specified by one
+switch port end; the script finds the remote end automatically.
+.SS OPTIONS
+.INDENT 0.0
+.TP
+.B \fB\-h\fP
+show help
+.TP
+.B \fB\-R\fP
+Recalculate the ibnetdiscover information, ie do not use the cached
+information. This option is slower but should be used if the diag
+tools have not been used for some time or if there are other reasons to
+believe that the fabric has changed.
+.UNINDENT
+.sp
+\fB\-C <ca_name>\fP use the specified ca_name.
+.sp
+\fB\-P <ca_port>\fP use the specified ca_port.
+.SS FILES
+.\" Common text for the config file
+.
+.SS CONFIG FILE
+.sp
+/etc/infiniband-diags/ibdiag.conf
+.sp
+A global config file is provided to set some of the common options for all
+tools. See supplied config file for details.
+.\" Common text to describe the node name map file.
+.
+.SS NODE NAME MAP FILE FORMAT
+.sp
+The node name map is used to specify user friendly names for nodes in the
+output. GUIDs are used to perform the lookup.
+.sp
+This functionality is provided by the opensm\-libs package. See \fBopensm(8)\fP
+for the file location for your installation.
+.sp
+\fBGenerically:\fP
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+# comment
+<guid> "<name>"
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+\fBExample:\fP
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+# IB1
+# Line cards
+0x0008f104003f125c "IB1 (Rack 11 slot 1 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f125d "IB1 (Rack 11 slot 1 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f10d2 "IB1 (Rack 11 slot 2 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f10d3 "IB1 (Rack 11 slot 2 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f10bf "IB1 (Rack 11 slot 12 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+
+# Spines
+0x0008f10400400e2d "IB1 (Rack 11 spine 1 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e2e "IB1 (Rack 11 spine 1 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e2f "IB1 (Rack 11 spine 1 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e31 "IB1 (Rack 11 spine 2 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e32 "IB1 (Rack 11 spine 2 ) ISR9288 Voltaire sFB\-12D"
+
+# GUID Node Name
+0x0008f10400411a08 "SW1 (Rack 3) ISR9024 Voltaire 9024D"
+0x0008f10400411a28 "SW2 (Rack 3) ISR9024 Voltaire 9024D"
+0x0008f10400411a34 "SW3 (Rack 3) ISR9024 Voltaire 9024D"
+0x0008f104004119d0 "SW4 (Rack 3) ISR9024 Voltaire 9024D"
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SS AUTHOR
+.INDENT 0.0
+.TP
+.B Ira Weiny
+< \fI\%ira.weiny@intel.com\fP >
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/contrib/ofed/infiniband-diags/man/ibhosts.8 b/contrib/ofed/infiniband-diags/man/ibhosts.8
new file mode 100644
index 000000000000..067c36394c37
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/man/ibhosts.8
@@ -0,0 +1,184 @@
+.\" Man page generated from reStructuredText.
+.
+.TH IBHOSTS 8 "" "" "OpenIB Diagnostics"
+.SH NAME
+IBHOSTS \- show InfiniBand host nodes in topology
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.SH SYNOPSIS
+.sp
+ibhosts [options] [<topology\-file>]
+.SH DESCRIPTION
+.sp
+ibhosts is a script which either walks the IB subnet topology or uses an
+already saved topology file and extracts the CA nodes.
+.SH OPTIONS
+.\" Define the common option -C
+.
+.sp
+\fB\-C, \-\-Ca <ca_name>\fP use the specified ca_name.
+.\" Define the common option -P
+.
+.sp
+\fB\-P, \-\-Port <ca_port>\fP use the specified ca_port.
+.\" Define the common option -t
+.
+.sp
+\fB\-t, \-\-timeout <timeout_ms>\fP override the default timeout for the solicited mads.
+.\" Define the common option -y
+.
+.INDENT 0.0
+.TP
+.B \fB\-y, \-\-m_key <key>\fP
+use the specified M_key for requests. If non\-numeric value (like \(aqx\(aq)
+is specified then a value will be prompted for.
+.UNINDENT
+.\" Define the common option -h
+.
+.sp
+\fB\-h, \-\-help\fP show the usage message
+.\" Define the common option -z
+.
+.sp
+\fB\-\-config, \-z <config_file>\fP Specify alternate config file.
+.INDENT 0.0
+.INDENT 3.5
+Default: /etc/infiniband-diags/ibdiag.conf
+.UNINDENT
+.UNINDENT
+.\" Explanation of local port selection
+.
+.SS Local port Selection
+.sp
+Multiple port/Multiple CA support: when no IB device or port is specified
+(see the "local umad parameters" below), the libibumad library
+selects the port to use by the following criteria:
+.INDENT 0.0
+.INDENT 3.5
+.INDENT 0.0
+.IP 1. 3
+the first port that is ACTIVE.
+.IP 2. 3
+if not found, the first port that is UP (physical link up).
+.UNINDENT
+.sp
+If a port and/or CA name is specified, the libibumad library attempts
+to fulfill the user request, and will fail if it is not possible.
+.sp
+For example:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+ibaddr # use the first port (criteria #1 above)
+ibaddr \-C mthca1 # pick the best port from "mthca1" only.
+ibaddr \-P 2 # use the second (active/up) port from the first available IB device.
+ibaddr \-C mthca0 \-P 2 # use the specified port only.
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SH FILES
+.\" Common text for the config file
+.
+.SS CONFIG FILE
+.sp
+/etc/infiniband-diags/ibdiag.conf
+.sp
+A global config file is provided to set some of the common options for all
+tools. See supplied config file for details.
+.\" Common text to describe the node name map file.
+.
+.SS NODE NAME MAP FILE FORMAT
+.sp
+The node name map is used to specify user friendly names for nodes in the
+output. GUIDs are used to perform the lookup.
+.sp
+This functionality is provided by the opensm\-libs package. See \fBopensm(8)\fP
+for the file location for your installation.
+.sp
+\fBGenerically:\fP
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+# comment
+<guid> "<name>"
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+\fBExample:\fP
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+# IB1
+# Line cards
+0x0008f104003f125c "IB1 (Rack 11 slot 1 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f125d "IB1 (Rack 11 slot 1 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f10d2 "IB1 (Rack 11 slot 2 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f10d3 "IB1 (Rack 11 slot 2 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f10bf "IB1 (Rack 11 slot 12 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+
+# Spines
+0x0008f10400400e2d "IB1 (Rack 11 spine 1 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e2e "IB1 (Rack 11 spine 1 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e2f "IB1 (Rack 11 spine 1 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e31 "IB1 (Rack 11 spine 2 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e32 "IB1 (Rack 11 spine 2 ) ISR9288 Voltaire sFB\-12D"
+
+# GUID Node Name
+0x0008f10400411a08 "SW1 (Rack 3) ISR9024 Voltaire 9024D"
+0x0008f10400411a28 "SW2 (Rack 3) ISR9024 Voltaire 9024D"
+0x0008f10400411a34 "SW3 (Rack 3) ISR9024 Voltaire 9024D"
+0x0008f104004119d0 "SW4 (Rack 3) ISR9024 Voltaire 9024D"
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SH SEE ALSO
+.sp
+ibnetdiscover(8)
+.SH DEPENDENCIES
+.sp
+ibnetdiscover, ibnetdiscover format
+.SH AUTHOR
+.INDENT 0.0
+.TP
+.B Hal Rosenstock
+< \fI\%halr@voltaire.com\fP >
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/contrib/ofed/infiniband-diags/man/ibidsverify.8 b/contrib/ofed/infiniband-diags/man/ibidsverify.8
new file mode 100644
index 000000000000..1df287b77d5f
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/man/ibidsverify.8
@@ -0,0 +1,80 @@
+.\" Man page generated from reStructuredText.
+.
+.TH IBIDSVERIFY 8 "" "" "Open IB Diagnostics"
+.SH NAME
+IBIDSVERIFY \-
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.SH VALIDATE IB IDENTIFIERS IN SUBNET AND REPORT ERRORS
+.SS SYNOPSIS
+.sp
+ibidsverify.pl [\-h] [\-R]
+.SS DESCRIPTION
+.sp
+ibidsverify.pl is a perl script which uses a full topology file that was
+created by ibnetdiscover, scans the network to validate the LIDs and GUIDs
+in the subnet. The validation consists of checking that there are no zero
+or duplicate identifiers.
+.sp
+Finally, ibidsverify.pl will also reuse the cached ibnetdiscover output from
+some of the other diag tools which makes it a bit faster than running
+ibnetdiscover from scratch.
+.SS OPTIONS
+.sp
+\fB\-R\fP
+Recalculate the ibnetdiscover information, ie do not use the cached
+information. This option is slower but should be used if the diag tools have
+not been used for some time or if there are other reasons to believe the
+fabric has changed.
+.sp
+\fB\-C <ca_name>\fP use the specified ca_name.
+.sp
+\fB\-P <ca_port>\fP use the specified ca_port.
+.SS EXIT STATUS
+.sp
+Exit status is 1 if errors are found, 0 otherwise.
+.SS FILES
+.\" Common text for the config file
+.
+.SS CONFIG FILE
+.sp
+/etc/infiniband-diags/ibdiag.conf
+.sp
+A global config file is provided to set some of the common options for all
+tools. See supplied config file for details.
+.SS SEE ALSO
+.sp
+\fBibnetdiscover(8)\fP
+.SS AUTHOR
+.INDENT 0.0
+.TP
+.B Hal Rosenstock
+< \fI\%halr@voltaire.com\fP >
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/contrib/ofed/infiniband-diags/man/iblinkinfo.8 b/contrib/ofed/infiniband-diags/man/iblinkinfo.8
new file mode 100644
index 000000000000..2a571e353273
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/man/iblinkinfo.8
@@ -0,0 +1,319 @@
+.\" Man page generated from reStructuredText.
+.
+.TH IBLINKINFO 8 "" "" "OpenIB Diagnostics"
+.SH NAME
+IBLINKINFO \- report link info for all links in the fabric
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.SH SYNOPSIS
+.sp
+iblinkinfo <options>
+.SH DESCRIPTION
+.sp
+iblinkinfo reports link info for each port in an IB fabric, node by node.
+Optionally, iblinkinfo can do partial scans and limit its output to parts of a
+fabric.
+.SH OPTIONS
+.sp
+\fB\-\-down, \-d\fP
+Print only nodes which have a port in the "Down" state.
+.sp
+\fB\-\-line, \-l\fP
+Print all information for each link on one line. Default is to print a header
+with the node information and then a list for each port (useful for
+grep\(aqing output).
+.sp
+\fB\-\-additional, \-p\fP
+Print additional port settings (<LifeTime>,<HoqLife>,<VLStallCount>)
+.sp
+\fB\-\-switches\-only\fP
+Show only switches in output.
+.sp
+\fB\-\-cas\-only\fP
+Show only CAs in output.
+.SS Partial Scan flags
+.sp
+The node to start a partial scan can be specified with the following addresses.
+.\" Define the common option -G
+.
+.sp
+\fB\-\-port\-guid, \-G <port_guid>\fP Specify a port_guid
+.\" Define the common option -D for Directed routes
+.
+.sp
+\fB\-D, \-\-Direct <dr_path>\fP The address specified is a directed route
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+Examples:
+ \-D "0" # self port
+ \-D "0,1,2,1,4" # out via port 1, then 2, ...
+
+ (Note the second number in the path specified must match the port being
+ used. This can be specified using the port selection flag \(aq\-P\(aq or the
+ port found through the automatic selection process.)
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+\fBNote:\fP For switches results are printed for all ports not just switch port 0.
+.sp
+\fB\-\-switch, \-S <port_guid>\fP same as "\-G". (provided only for backward compatibility)
+.sp
+How much of the scan to be printed can be controled with the following.
+.sp
+\fB\-\-all, \-a\fP
+Print all nodes found in a partial fabric scan. Normally a
+partial fabric scan will return only the node specified. This option will
+print the other nodes found as well.
+.sp
+\fB\-\-hops, \-n <hops>\fP
+Specify the number of hops away from a specified node to scan. This is useful
+to expand a partial fabric scan beyond the node specified.
+.SS Cache File flags
+.\" Define the common option load-cache
+.
+.sp
+\fB\-\-load\-cache <filename>\fP
+Load and use the cached ibnetdiscover data stored in the specified
+filename. May be useful for outputting and learning about other
+fabrics or a previous state of a fabric.
+.\" Define the common option diff
+.
+.sp
+\fB\-\-diff <filename>\fP
+Load cached ibnetdiscover data and do a diff comparison to the current
+network or another cache. A special diff output for ibnetdiscover
+output will be displayed showing differences between the old and current
+fabric. By default, the following are compared for differences: switches,
+channel adapters, routers, and port connections.
+.\" Define the common option diffcheck
+.
+.sp
+\fB\-\-diffcheck <key(s)>\fP
+Specify what diff checks should be done in the \fB\-\-diff\fP option above.
+Comma separate multiple diff check key(s). The available diff checks
+are: \fBsw = switches\fP, \fBca = channel adapters\fP, \fBrouter\fP = routers,
+\fBport\fP = port connections, \fBlid\fP = lids, \fBnodedesc\fP = node
+descriptions. Note that \fBport\fP, \fBlid\fP, and \fBnodedesc\fP are
+checked only for the node types that are specified (e.g. \fBsw\fP,
+\fBca\fP, \fBrouter\fP). If \fBport\fP is specified alongside \fBlid\fP
+or \fBnodedesc\fP, remote port lids and node descriptions will also be compared.
+.sp
+\fB\-\-filterdownports <filename>\fP
+Filter downports indicated in a ibnetdiscover cache. If a port was previously
+indicated as down in the specified cache, and is still down, do not output it in the
+resulting output. This option may be particularly useful for environments
+where switches are not fully populated, thus much of the default iblinkinfo
+info is considered unuseful. See \fBibnetdiscover\fP for information on caching
+ibnetdiscover output.
+.SS Port Selection flags
+.\" Define the common option -C
+.
+.sp
+\fB\-C, \-\-Ca <ca_name>\fP use the specified ca_name.
+.\" Define the common option -P
+.
+.sp
+\fB\-P, \-\-Port <ca_port>\fP use the specified ca_port.
+.\" Explanation of local port selection
+.
+.SS Local port Selection
+.sp
+Multiple port/Multiple CA support: when no IB device or port is specified
+(see the "local umad parameters" below), the libibumad library
+selects the port to use by the following criteria:
+.INDENT 0.0
+.INDENT 3.5
+.INDENT 0.0
+.IP 1. 3
+the first port that is ACTIVE.
+.IP 2. 3
+if not found, the first port that is UP (physical link up).
+.UNINDENT
+.sp
+If a port and/or CA name is specified, the libibumad library attempts
+to fulfill the user request, and will fail if it is not possible.
+.sp
+For example:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+ibaddr # use the first port (criteria #1 above)
+ibaddr \-C mthca1 # pick the best port from "mthca1" only.
+ibaddr \-P 2 # use the second (active/up) port from the first available IB device.
+ibaddr \-C mthca0 \-P 2 # use the specified port only.
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS Configuration flags
+.\" Define the common option -z
+.
+.sp
+\fB\-\-config, \-z <config_file>\fP Specify alternate config file.
+.INDENT 0.0
+.INDENT 3.5
+Default: /etc/infiniband-diags/ibdiag.conf
+.UNINDENT
+.UNINDENT
+.\" Define the common option -z
+.
+.INDENT 0.0
+.TP
+.B \fB\-\-outstanding_smps, \-o <val>\fP
+Specify the number of outstanding SMP\(aqs which should be issued during the scan
+.sp
+Default: 2
+.UNINDENT
+.\" Define the common option --node-name-map
+.
+.sp
+\fB\-\-node\-name\-map <node\-name\-map>\fP Specify a node name map.
+.INDENT 0.0
+.INDENT 3.5
+This file maps GUIDs to more user friendly names. See FILES section.
+.UNINDENT
+.UNINDENT
+.\" Define the common option -t
+.
+.sp
+\fB\-t, \-\-timeout <timeout_ms>\fP override the default timeout for the solicited mads.
+.\" Define the common option -y
+.
+.INDENT 0.0
+.TP
+.B \fB\-y, \-\-m_key <key>\fP
+use the specified M_key for requests. If non\-numeric value (like \(aqx\(aq)
+is specified then a value will be prompted for.
+.UNINDENT
+.SS Debugging flags
+.\" Define the common option -e
+.
+.INDENT 0.0
+.TP
+.B \-e
+show send and receive errors (timeouts and others)
+.UNINDENT
+.\" Define the common option -h
+.
+.sp
+\fB\-h, \-\-help\fP show the usage message
+.\" Define the common option -v
+.
+.INDENT 0.0
+.TP
+.B \fB\-v, \-\-verbose\fP
+increase the application verbosity level.
+May be used several times (\-vv or \-v \-v \-v)
+.UNINDENT
+.\" Define the common option -V
+.
+.sp
+\fB\-V, \-\-version\fP show the version info.
+.SH EXIT STATUS
+.sp
+0 on success, \-1 on failure to scan the fabric, 1 if check mode is used and
+inconsistencies are found.
+.SH FILES
+.\" Common text for the config file
+.
+.SS CONFIG FILE
+.sp
+/etc/infiniband-diags/ibdiag.conf
+.sp
+A global config file is provided to set some of the common options for all
+tools. See supplied config file for details.
+.\" Common text to describe the node name map file.
+.
+.SS NODE NAME MAP FILE FORMAT
+.sp
+The node name map is used to specify user friendly names for nodes in the
+output. GUIDs are used to perform the lookup.
+.sp
+This functionality is provided by the opensm\-libs package. See \fBopensm(8)\fP
+for the file location for your installation.
+.sp
+\fBGenerically:\fP
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+# comment
+<guid> "<name>"
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+\fBExample:\fP
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+# IB1
+# Line cards
+0x0008f104003f125c "IB1 (Rack 11 slot 1 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f125d "IB1 (Rack 11 slot 1 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f10d2 "IB1 (Rack 11 slot 2 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f10d3 "IB1 (Rack 11 slot 2 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f10bf "IB1 (Rack 11 slot 12 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+
+# Spines
+0x0008f10400400e2d "IB1 (Rack 11 spine 1 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e2e "IB1 (Rack 11 spine 1 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e2f "IB1 (Rack 11 spine 1 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e31 "IB1 (Rack 11 spine 2 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e32 "IB1 (Rack 11 spine 2 ) ISR9288 Voltaire sFB\-12D"
+
+# GUID Node Name
+0x0008f10400411a08 "SW1 (Rack 3) ISR9024 Voltaire 9024D"
+0x0008f10400411a28 "SW2 (Rack 3) ISR9024 Voltaire 9024D"
+0x0008f10400411a34 "SW3 (Rack 3) ISR9024 Voltaire 9024D"
+0x0008f104004119d0 "SW4 (Rack 3) ISR9024 Voltaire 9024D"
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SH AUTHOR
+.INDENT 0.0
+.TP
+.B Ira Weiny
+< \fI\%ira.weiny@intel.com\fP >
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/contrib/ofed/infiniband-diags/man/ibnetdiscover.8 b/contrib/ofed/infiniband-diags/man/ibnetdiscover.8
new file mode 100644
index 000000000000..4a4d54cf1100
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/man/ibnetdiscover.8
@@ -0,0 +1,399 @@
+.\" Man page generated from reStructuredText.
+.
+.TH IBNETDISCOVER 8 "" "" "Open IB Diagnostics"
+.SH NAME
+IBNETDISCOVER \- discover InfiniBand topology
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.SH SYNOPSIS
+.sp
+ibnetdiscover [options] [<topology\-file>]
+.SH DESCRIPTION
+.sp
+ibnetdiscover performs IB subnet discovery and outputs a human readable
+topology file. GUIDs, node types, and port numbers are displayed
+as well as port LIDs and NodeDescriptions. All nodes (and links) are displayed
+(full topology). Optionally, this utility can be used to list the current
+connected nodes by nodetype. The output is printed to standard output
+unless a topology file is specified.
+.SH OPTIONS
+.sp
+\fB\-l, \-\-list\fP
+List of connected nodes
+.sp
+\fB\-g, \-\-grouping\fP
+Show grouping. Grouping correlates IB nodes by different vendor specific
+schemes. It may also show the switch external ports correspondence.
+.sp
+\fB\-H, \-\-Hca_list\fP
+List of connected CAs
+.sp
+\fB\-S, \-\-Switch_list\fP
+List of connected switches
+.sp
+\fB\-R, \-\-Router_list\fP
+List of connected routers
+.sp
+\fB\-s, \-\-show\fP
+Show progress information during discovery.
+.sp
+\fB\-f, \-\-full\fP
+Show full information (ports\(aq speed and width, vlcap)
+.sp
+\fB\-p, \-\-ports\fP
+Obtain a ports report which is a
+list of connected ports with relevant information (like LID, portnum,
+GUID, width, speed, and NodeDescription).
+.sp
+\fB\-m, \-\-max_hops\fP
+Report max hops discovered.
+.\" Define the common option -z
+.
+.INDENT 0.0
+.TP
+.B \fB\-\-outstanding_smps, \-o <val>\fP
+Specify the number of outstanding SMP\(aqs which should be issued during the scan
+.sp
+Default: 2
+.UNINDENT
+.SS Cache File flags
+.\" Define the common option cache
+.
+.sp
+\fB\-\-cache <filename>\fP
+Cache the ibnetdiscover network data in the specified filename. This
+cache may be used by other tools for later analysis.
+.\" Define the common option load-cache
+.
+.sp
+\fB\-\-load\-cache <filename>\fP
+Load and use the cached ibnetdiscover data stored in the specified
+filename. May be useful for outputting and learning about other
+fabrics or a previous state of a fabric.
+.\" Define the common option diff
+.
+.sp
+\fB\-\-diff <filename>\fP
+Load cached ibnetdiscover data and do a diff comparison to the current
+network or another cache. A special diff output for ibnetdiscover
+output will be displayed showing differences between the old and current
+fabric. By default, the following are compared for differences: switches,
+channel adapters, routers, and port connections.
+.\" Define the common option diffcheck
+.
+.sp
+\fB\-\-diffcheck <key(s)>\fP
+Specify what diff checks should be done in the \fB\-\-diff\fP option above.
+Comma separate multiple diff check key(s). The available diff checks
+are: \fBsw = switches\fP, \fBca = channel adapters\fP, \fBrouter\fP = routers,
+\fBport\fP = port connections, \fBlid\fP = lids, \fBnodedesc\fP = node
+descriptions. Note that \fBport\fP, \fBlid\fP, and \fBnodedesc\fP are
+checked only for the node types that are specified (e.g. \fBsw\fP,
+\fBca\fP, \fBrouter\fP). If \fBport\fP is specified alongside \fBlid\fP
+or \fBnodedesc\fP, remote port lids and node descriptions will also be compared.
+.SS Port Selection flags
+.\" Define the common option -C
+.
+.sp
+\fB\-C, \-\-Ca <ca_name>\fP use the specified ca_name.
+.\" Define the common option -P
+.
+.sp
+\fB\-P, \-\-Port <ca_port>\fP use the specified ca_port.
+.\" Explanation of local port selection
+.
+.SS Local port Selection
+.sp
+Multiple port/Multiple CA support: when no IB device or port is specified
+(see the "local umad parameters" below), the libibumad library
+selects the port to use by the following criteria:
+.INDENT 0.0
+.INDENT 3.5
+.INDENT 0.0
+.IP 1. 3
+the first port that is ACTIVE.
+.IP 2. 3
+if not found, the first port that is UP (physical link up).
+.UNINDENT
+.sp
+If a port and/or CA name is specified, the libibumad library attempts
+to fulfill the user request, and will fail if it is not possible.
+.sp
+For example:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+ibaddr # use the first port (criteria #1 above)
+ibaddr \-C mthca1 # pick the best port from "mthca1" only.
+ibaddr \-P 2 # use the second (active/up) port from the first available IB device.
+ibaddr \-C mthca0 \-P 2 # use the specified port only.
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS Configuration flags
+.\" Define the common option -z
+.
+.sp
+\fB\-\-config, \-z <config_file>\fP Specify alternate config file.
+.INDENT 0.0
+.INDENT 3.5
+Default: /etc/infiniband-diags/ibdiag.conf
+.UNINDENT
+.UNINDENT
+.\" Define the common option -z
+.
+.INDENT 0.0
+.TP
+.B \fB\-\-outstanding_smps, \-o <val>\fP
+Specify the number of outstanding SMP\(aqs which should be issued during the scan
+.sp
+Default: 2
+.UNINDENT
+.\" Define the common option --node-name-map
+.
+.sp
+\fB\-\-node\-name\-map <node\-name\-map>\fP Specify a node name map.
+.INDENT 0.0
+.INDENT 3.5
+This file maps GUIDs to more user friendly names. See FILES section.
+.UNINDENT
+.UNINDENT
+.\" Define the common option -t
+.
+.sp
+\fB\-t, \-\-timeout <timeout_ms>\fP override the default timeout for the solicited mads.
+.\" Define the common option -y
+.
+.INDENT 0.0
+.TP
+.B \fB\-y, \-\-m_key <key>\fP
+use the specified M_key for requests. If non\-numeric value (like \(aqx\(aq)
+is specified then a value will be prompted for.
+.UNINDENT
+.SS Debugging flags
+.\" Define the common option -d
+.
+.INDENT 0.0
+.TP
+.B \-d
+raise the IB debugging level.
+May be used several times (\-ddd or \-d \-d \-d).
+.UNINDENT
+.\" Define the common option -e
+.
+.INDENT 0.0
+.TP
+.B \-e
+show send and receive errors (timeouts and others)
+.UNINDENT
+.\" Define the common option -h
+.
+.sp
+\fB\-h, \-\-help\fP show the usage message
+.\" Define the common option -v
+.
+.INDENT 0.0
+.TP
+.B \fB\-v, \-\-verbose\fP
+increase the application verbosity level.
+May be used several times (\-vv or \-v \-v \-v)
+.UNINDENT
+.\" Define the common option -V
+.
+.sp
+\fB\-V, \-\-version\fP show the version info.
+.SH FILES
+.\" Common text for the config file
+.
+.SS CONFIG FILE
+.sp
+/etc/infiniband-diags/ibdiag.conf
+.sp
+A global config file is provided to set some of the common options for all
+tools. See supplied config file for details.
+.\" Common text to describe the node name map file.
+.
+.SS NODE NAME MAP FILE FORMAT
+.sp
+The node name map is used to specify user friendly names for nodes in the
+output. GUIDs are used to perform the lookup.
+.sp
+This functionality is provided by the opensm\-libs package. See \fBopensm(8)\fP
+for the file location for your installation.
+.sp
+\fBGenerically:\fP
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+# comment
+<guid> "<name>"
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+\fBExample:\fP
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+# IB1
+# Line cards
+0x0008f104003f125c "IB1 (Rack 11 slot 1 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f125d "IB1 (Rack 11 slot 1 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f10d2 "IB1 (Rack 11 slot 2 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f10d3 "IB1 (Rack 11 slot 2 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f10bf "IB1 (Rack 11 slot 12 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+
+# Spines
+0x0008f10400400e2d "IB1 (Rack 11 spine 1 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e2e "IB1 (Rack 11 spine 1 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e2f "IB1 (Rack 11 spine 1 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e31 "IB1 (Rack 11 spine 2 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e32 "IB1 (Rack 11 spine 2 ) ISR9288 Voltaire sFB\-12D"
+
+# GUID Node Name
+0x0008f10400411a08 "SW1 (Rack 3) ISR9024 Voltaire 9024D"
+0x0008f10400411a28 "SW2 (Rack 3) ISR9024 Voltaire 9024D"
+0x0008f10400411a34 "SW3 (Rack 3) ISR9024 Voltaire 9024D"
+0x0008f104004119d0 "SW4 (Rack 3) ISR9024 Voltaire 9024D"
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.\" Common text to describe the Topology file.
+.
+.SS TOPOLOGY FILE FORMAT
+.sp
+The topology file format is human readable and largely intuitive.
+Most identifiers are given textual names like vendor ID (vendid), device ID
+(device ID), GUIDs of various types (sysimgguid, caguid, switchguid, etc.).
+PortGUIDs are shown in parentheses (). For switches, this is shown on the
+switchguid line. For CA and router ports, it is shown on the connectivity
+lines. The IB node is identified followed by the number of ports and a quoted
+the node GUID. On the right of this line is a comment (#) followed by the
+NodeDescription in quotes. If the node is a switch, this line also contains
+whether switch port 0 is base or enhanced, and the LID and LMC of port 0.
+Subsequent lines pertaining to this node show the connectivity. On the
+left is the port number of the current node. On the right is the peer node
+(node at other end of link). It is identified in quotes with nodetype
+followed by \- followed by NodeGUID with the port number in square brackets.
+Further on the right is a comment (#). What follows the comment is
+dependent on the node type. If it it a switch node, it is followed by
+the NodeDescription in quotes and the LID of the peer node. If it is a
+CA or router node, it is followed by the local LID and LMC and then
+followed by the NodeDescription in quotes and the LID of the peer node.
+The active link width and speed are then appended to the end of this
+output line.
+.sp
+An example of this is:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+#
+# Topology file: generated on Tue Jun 5 14:15:10 2007
+#
+# Max of 3 hops discovered
+# Initiated from node 0008f10403960558 port 0008f10403960559
+
+Non\-Chassis Nodes
+
+vendid=0x8f1
+devid=0x5a06
+sysimgguid=0x5442ba00003000
+switchguid=0x5442ba00003080(5442ba00003080)
+Switch 24 "S\-005442ba00003080" # "ISR9024 Voltaire" base port 0 lid 6 lmc 0
+[22] "H\-0008f10403961354"[1](8f10403961355) # "MT23108 InfiniHost Mellanox Technologies" lid 4 4xSDR
+[10] "S\-0008f10400410015"[1] # "SW\-6IB4 Voltaire" lid 3 4xSDR
+[8] "H\-0008f10403960558"[2](8f1040396055a) # "MT23108 InfiniHost Mellanox Technologies" lid 14 4xSDR
+[6] "S\-0008f10400410015"[3] # "SW\-6IB4 Voltaire" lid 3 4xSDR
+[12] "H\-0008f10403960558"[1](8f10403960559) # "MT23108 InfiniHost Mellanox Technologies" lid 10 4xSDR
+
+vendid=0x8f1
+devid=0x5a05
+switchguid=0x8f10400410015(8f10400410015)
+Switch 8 "S\-0008f10400410015" # "SW\-6IB4 Voltaire" base port 0 lid 3 lmc 0
+[6] "H\-0008f10403960984"[1](8f10403960985) # "MT23108 InfiniHost Mellanox Technologies" lid 16 4xSDR
+[4] "H\-005442b100004900"[1](5442b100004901) # "MT23108 InfiniHost Mellanox Technologies" lid 12 4xSDR
+[1] "S\-005442ba00003080"[10] # "ISR9024 Voltaire" lid 6 1xSDR
+[3] "S\-005442ba00003080"[6] # "ISR9024 Voltaire" lid 6 4xSDR
+
+vendid=0x2c9
+devid=0x5a44
+caguid=0x8f10403960984
+Ca 2 "H\-0008f10403960984" # "MT23108 InfiniHost Mellanox Technologies"
+[1](8f10403960985) "S\-0008f10400410015"[6] # lid 16 lmc 1 "SW\-6IB4 Voltaire" lid 3 4xSDR
+
+vendid=0x2c9
+devid=0x5a44
+caguid=0x5442b100004900
+Ca 2 "H\-005442b100004900" # "MT23108 InfiniHost Mellanox Technologies"
+[1](5442b100004901) "S\-0008f10400410015"[4] # lid 12 lmc 1 "SW\-6IB4 Voltaire" lid 3 4xSDR
+
+vendid=0x2c9
+devid=0x5a44
+caguid=0x8f10403961354
+Ca 2 "H\-0008f10403961354" # "MT23108 InfiniHost Mellanox Technologies"
+[1](8f10403961355) "S\-005442ba00003080"[22] # lid 4 lmc 1 "ISR9024 Voltaire" lid 6 4xSDR
+
+vendid=0x2c9
+devid=0x5a44
+caguid=0x8f10403960558
+Ca 2 "H\-0008f10403960558" # "MT23108 InfiniHost Mellanox Technologies"
+[2](8f1040396055a) "S\-005442ba00003080"[8] # lid 14 lmc 1 "ISR9024 Voltaire" lid 6 4xSDR
+[1](8f10403960559) "S\-005442ba00003080"[12] # lid 10 lmc 1 "ISR9024 Voltaire" lid 6 1xSDR
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+When grouping is used, IB nodes are organized into chassis which are
+numbered. Nodes which cannot be determined to be in a chassis are
+displayed as "Non\-Chassis Nodes". External ports are also shown on the
+connectivity lines.
+.SH AUTHORS
+.INDENT 0.0
+.TP
+.B Hal Rosenstock
+< \fI\%halr@voltaire.com\fP >
+.TP
+.B Ira Weiny
+< \fI\%ira.weiny@intel.com\fP >
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/contrib/ofed/infiniband-diags/man/ibnodes.8 b/contrib/ofed/infiniband-diags/man/ibnodes.8
new file mode 100644
index 000000000000..03f8c14ed0fe
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/man/ibnodes.8
@@ -0,0 +1,176 @@
+.\" Man page generated from reStructuredText.
+.
+.TH IBNODES 8 "" "" "OpenIB Diagnostics"
+.SH NAME
+IBNODES \- show InfiniBand nodes in topology
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.SH SYNOPSIS
+.sp
+ibnodes [options] [<topology\-file>]
+.SH DESCRIPTION
+.sp
+ibnodes is a script which either walks the IB subnet topology or uses an
+already saved topology file and extracts the IB nodes (CAs and switches).
+.SH OPTIONS
+.\" Define the common option -C
+.
+.sp
+\fB\-C, \-\-Ca <ca_name>\fP use the specified ca_name.
+.\" Define the common option -P
+.
+.sp
+\fB\-P, \-\-Port <ca_port>\fP use the specified ca_port.
+.\" Define the common option -t
+.
+.sp
+\fB\-t, \-\-timeout <timeout_ms>\fP override the default timeout for the solicited mads.
+.\" Define the common option -h
+.
+.sp
+\fB\-h, \-\-help\fP show the usage message
+.\" Define the common option -z
+.
+.sp
+\fB\-\-config, \-z <config_file>\fP Specify alternate config file.
+.INDENT 0.0
+.INDENT 3.5
+Default: /etc/infiniband-diags/ibdiag.conf
+.UNINDENT
+.UNINDENT
+.\" Explanation of local port selection
+.
+.SS Local port Selection
+.sp
+Multiple port/Multiple CA support: when no IB device or port is specified
+(see the "local umad parameters" below), the libibumad library
+selects the port to use by the following criteria:
+.INDENT 0.0
+.INDENT 3.5
+.INDENT 0.0
+.IP 1. 3
+the first port that is ACTIVE.
+.IP 2. 3
+if not found, the first port that is UP (physical link up).
+.UNINDENT
+.sp
+If a port and/or CA name is specified, the libibumad library attempts
+to fulfill the user request, and will fail if it is not possible.
+.sp
+For example:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+ibaddr # use the first port (criteria #1 above)
+ibaddr \-C mthca1 # pick the best port from "mthca1" only.
+ibaddr \-P 2 # use the second (active/up) port from the first available IB device.
+ibaddr \-C mthca0 \-P 2 # use the specified port only.
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SH FILES
+.\" Common text for the config file
+.
+.SS CONFIG FILE
+.sp
+/etc/infiniband-diags/ibdiag.conf
+.sp
+A global config file is provided to set some of the common options for all
+tools. See supplied config file for details.
+.\" Common text to describe the node name map file.
+.
+.SS NODE NAME MAP FILE FORMAT
+.sp
+The node name map is used to specify user friendly names for nodes in the
+output. GUIDs are used to perform the lookup.
+.sp
+This functionality is provided by the opensm\-libs package. See \fBopensm(8)\fP
+for the file location for your installation.
+.sp
+\fBGenerically:\fP
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+# comment
+<guid> "<name>"
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+\fBExample:\fP
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+# IB1
+# Line cards
+0x0008f104003f125c "IB1 (Rack 11 slot 1 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f125d "IB1 (Rack 11 slot 1 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f10d2 "IB1 (Rack 11 slot 2 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f10d3 "IB1 (Rack 11 slot 2 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f10bf "IB1 (Rack 11 slot 12 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+
+# Spines
+0x0008f10400400e2d "IB1 (Rack 11 spine 1 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e2e "IB1 (Rack 11 spine 1 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e2f "IB1 (Rack 11 spine 1 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e31 "IB1 (Rack 11 spine 2 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e32 "IB1 (Rack 11 spine 2 ) ISR9288 Voltaire sFB\-12D"
+
+# GUID Node Name
+0x0008f10400411a08 "SW1 (Rack 3) ISR9024 Voltaire 9024D"
+0x0008f10400411a28 "SW2 (Rack 3) ISR9024 Voltaire 9024D"
+0x0008f10400411a34 "SW3 (Rack 3) ISR9024 Voltaire 9024D"
+0x0008f104004119d0 "SW4 (Rack 3) ISR9024 Voltaire 9024D"
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SH SEE ALSO
+.sp
+ibnetdiscover(8)
+.SH DEPENDENCIES
+.sp
+ibnetdiscover, ibnetdiscover format
+.SH AUTHOR
+.INDENT 0.0
+.TP
+.B Hal Rosenstock
+< \fI\%halr@voltaire.com\fP >
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/contrib/ofed/infiniband-diags/man/ibping.8 b/contrib/ofed/infiniband-diags/man/ibping.8
new file mode 100644
index 000000000000..1fa53ad9464f
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/man/ibping.8
@@ -0,0 +1,177 @@
+.\" Man page generated from reStructuredText.
+.
+.TH IBPING 8 "" "" "Open IB Diagnostics"
+.SH NAME
+IBPING \- ping an InfiniBand address
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.SH SYNOPSIS
+.sp
+ibping [options] <dest lid | guid>
+.SH DESCRIPTION
+.sp
+ibping uses vendor mads to validate connectivity between IB nodes.
+On exit, (IP) ping like output is show. ibping is run as client/server.
+Default is to run as client. Note also that a default ping server is
+implemented within the kernel.
+.SH OPTIONS
+.sp
+\fB\-c, \-\-count\fP
+stop after count packets
+.sp
+\fB\-f, \-\-flood\fP
+flood destination: send packets back to back without delay
+.sp
+\fB\-o, \-\-oui\fP
+use specified OUI number to multiplex vendor mads
+.sp
+\fB\-S, \-\-Server\fP
+start in server mode (do not return)
+.sp
+\fB\-\-dgid <gid>\fP
+destination GID: use when GRH is required in packets (IPv6 format)
+.SS Addressing Flags
+.\" Define the common option -L
+.
+.sp
+\fB\-L, \-\-Lid\fP The address specified is a LID
+.\" Define the common option -G
+.
+.sp
+\fB\-G, \-\-Guid\fP The address specified is a Port GUID
+.\" Define the common option -s
+.
+.sp
+\fB\-s, \-\-sm_port <smlid>\fP use \(aqsmlid\(aq as the target lid for SA queries.
+.SS Port Selection flags
+.\" Define the common option -C
+.
+.sp
+\fB\-C, \-\-Ca <ca_name>\fP use the specified ca_name.
+.\" Define the common option -P
+.
+.sp
+\fB\-P, \-\-Port <ca_port>\fP use the specified ca_port.
+.\" Explanation of local port selection
+.
+.SS Local port Selection
+.sp
+Multiple port/Multiple CA support: when no IB device or port is specified
+(see the "local umad parameters" below), the libibumad library
+selects the port to use by the following criteria:
+.INDENT 0.0
+.INDENT 3.5
+.INDENT 0.0
+.IP 1. 3
+the first port that is ACTIVE.
+.IP 2. 3
+if not found, the first port that is UP (physical link up).
+.UNINDENT
+.sp
+If a port and/or CA name is specified, the libibumad library attempts
+to fulfill the user request, and will fail if it is not possible.
+.sp
+For example:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+ibaddr # use the first port (criteria #1 above)
+ibaddr \-C mthca1 # pick the best port from "mthca1" only.
+ibaddr \-P 2 # use the second (active/up) port from the first available IB device.
+ibaddr \-C mthca0 \-P 2 # use the specified port only.
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS Configuration flags
+.\" Define the common option -z
+.
+.sp
+\fB\-\-config, \-z <config_file>\fP Specify alternate config file.
+.INDENT 0.0
+.INDENT 3.5
+Default: /etc/infiniband-diags/ibdiag.conf
+.UNINDENT
+.UNINDENT
+.\" Define the common option -t
+.
+.sp
+\fB\-t, \-\-timeout <timeout_ms>\fP override the default timeout for the solicited mads.
+.SS Debugging flags
+.\" Define the common option -h
+.
+.sp
+\fB\-h, \-\-help\fP show the usage message
+.\" Define the common option -d
+.
+.INDENT 0.0
+.TP
+.B \-d
+raise the IB debugging level.
+May be used several times (\-ddd or \-d \-d \-d).
+.UNINDENT
+.\" Define the common option -e
+.
+.INDENT 0.0
+.TP
+.B \-e
+show send and receive errors (timeouts and others)
+.UNINDENT
+.\" Define the common option -v
+.
+.INDENT 0.0
+.TP
+.B \fB\-v, \-\-verbose\fP
+increase the application verbosity level.
+May be used several times (\-vv or \-v \-v \-v)
+.UNINDENT
+.\" Define the common option -V
+.
+.sp
+\fB\-V, \-\-version\fP show the version info.
+.SH FILES
+.\" Common text for the config file
+.
+.SS CONFIG FILE
+.sp
+/etc/infiniband-diags/ibdiag.conf
+.sp
+A global config file is provided to set some of the common options for all
+tools. See supplied config file for details.
+.SH AUTHOR
+.INDENT 0.0
+.TP
+.B Hal Rosenstock
+< \fI\%halr@voltaire.com\fP >
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/contrib/ofed/infiniband-diags/man/ibportstate.8 b/contrib/ofed/infiniband-diags/man/ibportstate.8
new file mode 100644
index 000000000000..2d7c85ff0be9
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/man/ibportstate.8
@@ -0,0 +1,259 @@
+.\" Man page generated from reStructuredText.
+.
+.TH IBPORTSTATE 8 "" "" "Open IB Diagnostics"
+.SH NAME
+IBPORTSTATE \- handle port (physical) state and link speed of an InfiniBand port
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.SH SYNOPSIS
+.sp
+ibportstate [options] <dest dr_path|lid|guid> <portnum> [<op>]
+.SH DESCRIPTION
+.sp
+ibportstate allows the port state and port physical state of an IB port
+to be queried (in addition to link width and speed being validated
+relative to the peer port when the port queried is a switch port),
+or a switch port to be disabled, enabled, or reset. It
+also allows the link speed/width enabled on any IB port to be adjusted.
+.SH OPTIONS
+.INDENT 0.0
+.TP
+.B \fB<op>\fP
+.INDENT 7.0
+.TP
+.B Supported ops: enable, disable, reset, speed, espeed, fdr10, width, query,
+on, off, down, arm, active, vls, mtu, lid, smlid, lmc,
+mkey, mkeylease, mkeyprot
+(Default is query)
+.UNINDENT
+.sp
+\fBenable, disable, and reset\fP are only allowed on switch ports (An
+error is indicated if attempted on CA or router ports)
+.sp
+\fBoff\fP change the port state to disable.
+.sp
+\fBon\fP change the port state to enable(only when the current state is disable).
+.sp
+\fBspeed and width\fP are allowed on any port
+.sp
+\fBspeed\fP values are the legal values for PortInfo:LinkSpeedEnabled (An
+error is indicated if PortInfo:LinkSpeedSupported does not support this
+setting)
+.sp
+\fBespeed\fP is allowed on any port supporting extended link speeds
+.sp
+\fBfdr10\fP is allowed on any port supporting fdr10 (An error is
+indicated if port\(aqs capability mask indicates extended link speeds are
+not supported or if PortInfo:LinkSpeedExtSupported does not support
+this setting)
+.sp
+\fBwidth\fP values are legal values for PortInfo:LinkWidthEnabled (An
+error is indicated if PortInfo:LinkWidthSupported does not support this
+setting) (NOTE: Speed and width changes are not effected until the port
+goes through link renegotiation)
+.sp
+\fBquery\fP also validates port characteristics (link width, speed,
+espeed, and fdr10) based on the peer port. This checking is done when
+the port queried is a switch port as it relies on combined routing (an
+initial LID route with directed routing to the peer) which can only be
+done on a switch. This peer port validation feature of query op
+requires LID routing to be functioning in the subnet.
+.sp
+\fBmkey, mkeylease, and mkeyprot\fP are only allowed on CAs, routers, or
+switch port 0 (An error is generated if attempted on external switch
+ports). Hexadecimal and octal mkeys may be specified by prepending the
+key with \(aq0x\(aq or \(aq0\(aq, respectively. If a non\-numeric value (like \(aqx\(aq)
+is specified for the mkey, then ibportstate will prompt for a value.
+.UNINDENT
+.SS Addressing Flags
+.\" Define the common option -L
+.
+.sp
+\fB\-L, \-\-Lid\fP The address specified is a LID
+.\" Define the common option -G
+.
+.sp
+\fB\-G, \-\-Guid\fP The address specified is a Port GUID
+.\" Define the common option -D for Directed routes
+.
+.sp
+\fB\-D, \-\-Direct\fP The address specified is a directed route
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+Examples:
+ [options] \-D [options] "0" # self port
+ [options] \-D [options] "0,1,2,1,4" # out via port 1, then 2, ...
+
+ (Note the second number in the path specified must match the port being
+ used. This can be specified using the port selection flag \(aq\-P\(aq or the
+ port found through the automatic selection process.)
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.\" Define the common option -s
+.
+.sp
+\fB\-s, \-\-sm_port <smlid>\fP use \(aqsmlid\(aq as the target lid for SA queries.
+.SS Port Selection flags
+.\" Define the common option -C
+.
+.sp
+\fB\-C, \-\-Ca <ca_name>\fP use the specified ca_name.
+.\" Define the common option -P
+.
+.sp
+\fB\-P, \-\-Port <ca_port>\fP use the specified ca_port.
+.\" Explanation of local port selection
+.
+.SS Local port Selection
+.sp
+Multiple port/Multiple CA support: when no IB device or port is specified
+(see the "local umad parameters" below), the libibumad library
+selects the port to use by the following criteria:
+.INDENT 0.0
+.INDENT 3.5
+.INDENT 0.0
+.IP 1. 3
+the first port that is ACTIVE.
+.IP 2. 3
+if not found, the first port that is UP (physical link up).
+.UNINDENT
+.sp
+If a port and/or CA name is specified, the libibumad library attempts
+to fulfill the user request, and will fail if it is not possible.
+.sp
+For example:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+ibaddr # use the first port (criteria #1 above)
+ibaddr \-C mthca1 # pick the best port from "mthca1" only.
+ibaddr \-P 2 # use the second (active/up) port from the first available IB device.
+ibaddr \-C mthca0 \-P 2 # use the specified port only.
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS Configuration flags
+.\" Define the common option -z
+.
+.sp
+\fB\-\-config, \-z <config_file>\fP Specify alternate config file.
+.INDENT 0.0
+.INDENT 3.5
+Default: /etc/infiniband-diags/ibdiag.conf
+.UNINDENT
+.UNINDENT
+.\" Define the common option -t
+.
+.sp
+\fB\-t, \-\-timeout <timeout_ms>\fP override the default timeout for the solicited mads.
+.\" Define the common option -y
+.
+.INDENT 0.0
+.TP
+.B \fB\-y, \-\-m_key <key>\fP
+use the specified M_key for requests. If non\-numeric value (like \(aqx\(aq)
+is specified then a value will be prompted for.
+.UNINDENT
+.SS Debugging flags
+.\" Define the common option -h
+.
+.sp
+\fB\-h, \-\-help\fP show the usage message
+.\" Define the common option -d
+.
+.INDENT 0.0
+.TP
+.B \-d
+raise the IB debugging level.
+May be used several times (\-ddd or \-d \-d \-d).
+.UNINDENT
+.\" Define the common option -e
+.
+.INDENT 0.0
+.TP
+.B \-e
+show send and receive errors (timeouts and others)
+.UNINDENT
+.\" Define the common option -K
+.
+.INDENT 0.0
+.TP
+.B \fB\-K, \-\-show_keys\fP
+show security keys (mkey, smkey, etc.) associated with the request.
+.UNINDENT
+.\" Define the common option -v
+.
+.INDENT 0.0
+.TP
+.B \fB\-v, \-\-verbose\fP
+increase the application verbosity level.
+May be used several times (\-vv or \-v \-v \-v)
+.UNINDENT
+.\" Define the common option -V
+.
+.sp
+\fB\-V, \-\-version\fP show the version info.
+.SH FILES
+.\" Common text for the config file
+.
+.SS CONFIG FILE
+.sp
+/etc/infiniband-diags/ibdiag.conf
+.sp
+A global config file is provided to set some of the common options for all
+tools. See supplied config file for details.
+.SH EXAMPLES
+.INDENT 0.0
+.TP
+.B ::
+ibportstate 3 1 disable # by lid
+ibportstate \-G 0x2C9000100D051 1 enable # by guid
+ibportstate \-D 0 1 # (query) by direct route
+ibportstate 3 1 reset # by lid
+ibportstate 3 1 speed 1 # by lid
+ibportstate 3 1 width 1 # by lid
+ibportstate \-D 0 1 lid 0x1234 arm # by direct route
+.UNINDENT
+.SH AUTHOR
+.INDENT 0.0
+.TP
+.B Hal Rosenstock
+< \fI\%hal.rosenstock@gmail.com\fP >
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/contrib/ofed/infiniband-diags/man/ibqueryerrors.8 b/contrib/ofed/infiniband-diags/man/ibqueryerrors.8
new file mode 100644
index 000000000000..be9f3c086115
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/man/ibqueryerrors.8
@@ -0,0 +1,339 @@
+.\" Man page generated from reStructuredText.
+.
+.TH IBQUERYERRORS 8 "" "" "OpenIB Diagnostics"
+.SH NAME
+IBQUERYERRORS \- query and report IB port counters
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.SH SYNOPSIS
+.sp
+ibqueryerrors [options]
+.SH DESCRIPTION
+.sp
+The default behavior is to report the port error counters which exceed a
+threshold for each port in the fabric. The default threshold is zero (0).
+Error fields can also be suppressed entirely.
+.sp
+In addition to reporting errors on every port. ibqueryerrors can report the
+port transmit and receive data as well as report full link information to the
+remote port if available.
+.SH OPTIONS
+.sp
+\fB\-s, \-\-suppress <err1,err2,...>\fP
+Suppress the errors listed in the comma separated list provided.
+.sp
+\fB\-c, \-\-suppress\-common\fP
+Suppress some of the common "side effect" counters. These counters usually do
+not indicate an error condition and can be usually be safely ignored.
+.sp
+\fB\-r, \-\-report\-port\fP
+Report the port information. This includes LID, port, external port (if
+applicable), link speed setting, remote GUID, remote port, remote external port
+(if applicable), and remote node description information.
+.sp
+\fB\-\-data\fP
+Include the optional transmit and receive data counters.
+.sp
+\fB\-\-threshold\-file <filename>\fP
+Specify an alternate threshold file. The default is /etc/infiniband-diags/error_thresholds
+.sp
+\fB\-\-switch\fP print data for switch\(aqs only
+.sp
+\fB\-\-ca\fP print data for CA\(aqs only
+.sp
+\fB\-\-skip\-sl\fP Use the default sl for queries. This is not recommended when
+using a QoS aware routing engine as it can cause a credit deadlock.
+.sp
+\fB\-\-router\fP print data for routers only
+.sp
+\fB\-\-clear\-errors \-k\fP Clear error counters after read.
+.sp
+\fB\-\-clear\-counts \-K\fP Clear data counters after read.
+.sp
+\fBCAUTION\fP clearing data or error counters will occur regardless of if they
+are printed or not. See \fB\-\-counters\fP and \fB\-\-data\fP for details on
+controling which counters are printed.
+.sp
+\fB\-\-details\fP include receive error and transmit discard details
+.sp
+\fB\-\-counters\fP print data counters only
+.SS Partial Scan flags
+.sp
+The node to start a partial scan can be specified with the following addresses.
+.\" Define the common option -G
+.
+.sp
+\fB\-\-port\-guid, \-G <port_guid>\fP Specify a port_guid
+.\" Define the common option -D for Directed routes
+.
+.sp
+\fB\-D, \-\-Direct <dr_path>\fP The address specified is a directed route
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+Examples:
+ \-D "0" # self port
+ \-D "0,1,2,1,4" # out via port 1, then 2, ...
+
+ (Note the second number in the path specified must match the port being
+ used. This can be specified using the port selection flag \(aq\-P\(aq or the
+ port found through the automatic selection process.)
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+\fBNote:\fP For switches results are printed for all ports not just switch port 0.
+.sp
+\fB\-S <port_guid>\fP same as "\-G". (provided only for backward compatibility)
+.SS Cache File flags
+.\" Define the common option load-cache
+.
+.sp
+\fB\-\-load\-cache <filename>\fP
+Load and use the cached ibnetdiscover data stored in the specified
+filename. May be useful for outputting and learning about other
+fabrics or a previous state of a fabric.
+.SS Port Selection flags
+.\" Define the common option -C
+.
+.sp
+\fB\-C, \-\-Ca <ca_name>\fP use the specified ca_name.
+.\" Define the common option -P
+.
+.sp
+\fB\-P, \-\-Port <ca_port>\fP use the specified ca_port.
+.\" Explanation of local port selection
+.
+.SS Local port Selection
+.sp
+Multiple port/Multiple CA support: when no IB device or port is specified
+(see the "local umad parameters" below), the libibumad library
+selects the port to use by the following criteria:
+.INDENT 0.0
+.INDENT 3.5
+.INDENT 0.0
+.IP 1. 3
+the first port that is ACTIVE.
+.IP 2. 3
+if not found, the first port that is UP (physical link up).
+.UNINDENT
+.sp
+If a port and/or CA name is specified, the libibumad library attempts
+to fulfill the user request, and will fail if it is not possible.
+.sp
+For example:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+ibaddr # use the first port (criteria #1 above)
+ibaddr \-C mthca1 # pick the best port from "mthca1" only.
+ibaddr \-P 2 # use the second (active/up) port from the first available IB device.
+ibaddr \-C mthca0 \-P 2 # use the specified port only.
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS Configuration flags
+.\" Define the common option -z
+.
+.sp
+\fB\-\-config, \-z <config_file>\fP Specify alternate config file.
+.INDENT 0.0
+.INDENT 3.5
+Default: /etc/infiniband-diags/ibdiag.conf
+.UNINDENT
+.UNINDENT
+.\" Define the common option -z
+.
+.INDENT 0.0
+.TP
+.B \fB\-\-outstanding_smps, \-o <val>\fP
+Specify the number of outstanding SMP\(aqs which should be issued during the scan
+.sp
+Default: 2
+.UNINDENT
+.\" Define the common option --node-name-map
+.
+.sp
+\fB\-\-node\-name\-map <node\-name\-map>\fP Specify a node name map.
+.INDENT 0.0
+.INDENT 3.5
+This file maps GUIDs to more user friendly names. See FILES section.
+.UNINDENT
+.UNINDENT
+.\" Define the common option -t
+.
+.sp
+\fB\-t, \-\-timeout <timeout_ms>\fP override the default timeout for the solicited mads.
+.\" Define the common option -y
+.
+.INDENT 0.0
+.TP
+.B \fB\-y, \-\-m_key <key>\fP
+use the specified M_key for requests. If non\-numeric value (like \(aqx\(aq)
+is specified then a value will be prompted for.
+.UNINDENT
+.SS Debugging flags
+.\" Define the common option -d
+.
+.INDENT 0.0
+.TP
+.B \-d
+raise the IB debugging level.
+May be used several times (\-ddd or \-d \-d \-d).
+.UNINDENT
+.\" Define the common option -e
+.
+.INDENT 0.0
+.TP
+.B \-e
+show send and receive errors (timeouts and others)
+.UNINDENT
+.\" Define the common option -h
+.
+.sp
+\fB\-h, \-\-help\fP show the usage message
+.\" Define the common option -v
+.
+.INDENT 0.0
+.TP
+.B \fB\-v, \-\-verbose\fP
+increase the application verbosity level.
+May be used several times (\-vv or \-v \-v \-v)
+.UNINDENT
+.\" Define the common option -V
+.
+.sp
+\fB\-V, \-\-version\fP show the version info.
+.sp
+\fB\-R\fP (This option is obsolete and does nothing)
+.SH EXIT STATUS
+.sp
+\fB\-1\fP if scan fails.
+.sp
+\fB0\fP if scan succeeds without errors beyond thresholds
+.sp
+\fB1\fP if errors are found beyond thresholds or inconsistencies are found in check mode.
+.SH FILES
+.SS ERROR THRESHOLD
+.sp
+/etc/infiniband-diags/error_thresholds
+.sp
+Define threshold values for errors. File format is simple "name=val".
+Comments begin with \(aq#\(aq
+.sp
+\fBExample:\fP
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+# Define thresholds for error counters
+SymbolErrorCounter=10
+LinkErrorRecoveryCounter=10
+VL15Dropped=100
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.\" Common text for the config file
+.
+.SS CONFIG FILE
+.sp
+/etc/infiniband-diags/ibdiag.conf
+.sp
+A global config file is provided to set some of the common options for all
+tools. See supplied config file for details.
+.\" Common text to describe the node name map file.
+.
+.SS NODE NAME MAP FILE FORMAT
+.sp
+The node name map is used to specify user friendly names for nodes in the
+output. GUIDs are used to perform the lookup.
+.sp
+This functionality is provided by the opensm\-libs package. See \fBopensm(8)\fP
+for the file location for your installation.
+.sp
+\fBGenerically:\fP
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+# comment
+<guid> "<name>"
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+\fBExample:\fP
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+# IB1
+# Line cards
+0x0008f104003f125c "IB1 (Rack 11 slot 1 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f125d "IB1 (Rack 11 slot 1 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f10d2 "IB1 (Rack 11 slot 2 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f10d3 "IB1 (Rack 11 slot 2 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f10bf "IB1 (Rack 11 slot 12 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+
+# Spines
+0x0008f10400400e2d "IB1 (Rack 11 spine 1 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e2e "IB1 (Rack 11 spine 1 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e2f "IB1 (Rack 11 spine 1 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e31 "IB1 (Rack 11 spine 2 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e32 "IB1 (Rack 11 spine 2 ) ISR9288 Voltaire sFB\-12D"
+
+# GUID Node Name
+0x0008f10400411a08 "SW1 (Rack 3) ISR9024 Voltaire 9024D"
+0x0008f10400411a28 "SW2 (Rack 3) ISR9024 Voltaire 9024D"
+0x0008f10400411a34 "SW3 (Rack 3) ISR9024 Voltaire 9024D"
+0x0008f104004119d0 "SW4 (Rack 3) ISR9024 Voltaire 9024D"
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SH AUTHOR
+.INDENT 0.0
+.TP
+.B Ira Weiny
+< \fI\%ira.weiny@intel.com\fP >
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/contrib/ofed/infiniband-diags/man/ibroute.8 b/contrib/ofed/infiniband-diags/man/ibroute.8
new file mode 100644
index 000000000000..7c03c1295005
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/man/ibroute.8
@@ -0,0 +1,291 @@
+.\" Man page generated from reStructuredText.
+.
+.TH IBROUTE 8 "" "" "Open IB Diagnostics"
+.SH NAME
+IBROUTE \-
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.SH QUERY INFINIBAND SWITCH FORWARDING TABLES
+.SS SYNOPSIS
+.sp
+ibroute [options] [<dest dr_path|lid|guid> [<startlid> [<endlid>]]]
+.SS DESCRIPTION
+.sp
+ibroute uses SMPs to display the forwarding tables (unicast
+(LinearForwardingTable or LFT) or multicast (MulticastForwardingTable or MFT))
+for the specified switch LID and the optional lid (mlid) range.
+The default range is all valid entries in the range 1...FDBTop.
+.SS OPTIONS
+.INDENT 0.0
+.TP
+.B \fB\-a, \-\-all\fP
+show all lids in range, even invalid entries
+.TP
+.B \fB\-n, \-\-no_dests\fP
+do not try to resolve destinations
+.TP
+.B \fB\-M, \-\-Multicast\fP
+show multicast forwarding tables
+In this case, the range parameters are specifying the mlid range.
+.UNINDENT
+.SS Addressing Flags
+.\" Define the common option -D for Directed routes
+.
+.sp
+\fB\-D, \-\-Direct\fP The address specified is a directed route
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+Examples:
+ [options] \-D [options] "0" # self port
+ [options] \-D [options] "0,1,2,1,4" # out via port 1, then 2, ...
+
+ (Note the second number in the path specified must match the port being
+ used. This can be specified using the port selection flag \(aq\-P\(aq or the
+ port found through the automatic selection process.)
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.\" Define the common option -G
+.
+.sp
+\fB\-G, \-\-Guid\fP The address specified is a Port GUID
+.\" Define the common option -L
+.
+.sp
+\fB\-L, \-\-Lid\fP The address specified is a LID
+.\" Define the common option -s
+.
+.sp
+\fB\-s, \-\-sm_port <smlid>\fP use \(aqsmlid\(aq as the target lid for SA queries.
+.SS Port Selection flags
+.\" Define the common option -C
+.
+.sp
+\fB\-C, \-\-Ca <ca_name>\fP use the specified ca_name.
+.\" Define the common option -P
+.
+.sp
+\fB\-P, \-\-Port <ca_port>\fP use the specified ca_port.
+.\" Explanation of local port selection
+.
+.SS Local port Selection
+.sp
+Multiple port/Multiple CA support: when no IB device or port is specified
+(see the "local umad parameters" below), the libibumad library
+selects the port to use by the following criteria:
+.INDENT 0.0
+.INDENT 3.5
+.INDENT 0.0
+.IP 1. 3
+the first port that is ACTIVE.
+.IP 2. 3
+if not found, the first port that is UP (physical link up).
+.UNINDENT
+.sp
+If a port and/or CA name is specified, the libibumad library attempts
+to fulfill the user request, and will fail if it is not possible.
+.sp
+For example:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+ibaddr # use the first port (criteria #1 above)
+ibaddr \-C mthca1 # pick the best port from "mthca1" only.
+ibaddr \-P 2 # use the second (active/up) port from the first available IB device.
+ibaddr \-C mthca0 \-P 2 # use the specified port only.
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS Debugging flags
+.\" Define the common option -d
+.
+.INDENT 0.0
+.TP
+.B \-d
+raise the IB debugging level.
+May be used several times (\-ddd or \-d \-d \-d).
+.UNINDENT
+.\" Define the common option -e
+.
+.INDENT 0.0
+.TP
+.B \-e
+show send and receive errors (timeouts and others)
+.UNINDENT
+.\" Define the common option -h
+.
+.sp
+\fB\-h, \-\-help\fP show the usage message
+.\" Define the common option -v
+.
+.INDENT 0.0
+.TP
+.B \fB\-v, \-\-verbose\fP
+increase the application verbosity level.
+May be used several times (\-vv or \-v \-v \-v)
+.UNINDENT
+.\" Define the common option -V
+.
+.sp
+\fB\-V, \-\-version\fP show the version info.
+.SS Configuration flags
+.\" Define the common option -t
+.
+.sp
+\fB\-t, \-\-timeout <timeout_ms>\fP override the default timeout for the solicited mads.
+.\" Define the common option -y
+.
+.INDENT 0.0
+.TP
+.B \fB\-y, \-\-m_key <key>\fP
+use the specified M_key for requests. If non\-numeric value (like \(aqx\(aq)
+is specified then a value will be prompted for.
+.UNINDENT
+.\" Define the common option --node-name-map
+.
+.sp
+\fB\-\-node\-name\-map <node\-name\-map>\fP Specify a node name map.
+.INDENT 0.0
+.INDENT 3.5
+This file maps GUIDs to more user friendly names. See FILES section.
+.UNINDENT
+.UNINDENT
+.\" Define the common option -z
+.
+.sp
+\fB\-\-config, \-z <config_file>\fP Specify alternate config file.
+.INDENT 0.0
+.INDENT 3.5
+Default: /etc/infiniband-diags/ibdiag.conf
+.UNINDENT
+.UNINDENT
+.SS FILES
+.\" Common text for the config file
+.
+.SS CONFIG FILE
+.sp
+/etc/infiniband-diags/ibdiag.conf
+.sp
+A global config file is provided to set some of the common options for all
+tools. See supplied config file for details.
+.\" Common text to describe the node name map file.
+.
+.SS NODE NAME MAP FILE FORMAT
+.sp
+The node name map is used to specify user friendly names for nodes in the
+output. GUIDs are used to perform the lookup.
+.sp
+This functionality is provided by the opensm\-libs package. See \fBopensm(8)\fP
+for the file location for your installation.
+.sp
+\fBGenerically:\fP
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+# comment
+<guid> "<name>"
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+\fBExample:\fP
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+# IB1
+# Line cards
+0x0008f104003f125c "IB1 (Rack 11 slot 1 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f125d "IB1 (Rack 11 slot 1 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f10d2 "IB1 (Rack 11 slot 2 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f10d3 "IB1 (Rack 11 slot 2 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f10bf "IB1 (Rack 11 slot 12 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+
+# Spines
+0x0008f10400400e2d "IB1 (Rack 11 spine 1 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e2e "IB1 (Rack 11 spine 1 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e2f "IB1 (Rack 11 spine 1 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e31 "IB1 (Rack 11 spine 2 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e32 "IB1 (Rack 11 spine 2 ) ISR9288 Voltaire sFB\-12D"
+
+# GUID Node Name
+0x0008f10400411a08 "SW1 (Rack 3) ISR9024 Voltaire 9024D"
+0x0008f10400411a28 "SW2 (Rack 3) ISR9024 Voltaire 9024D"
+0x0008f10400411a34 "SW3 (Rack 3) ISR9024 Voltaire 9024D"
+0x0008f104004119d0 "SW4 (Rack 3) ISR9024 Voltaire 9024D"
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SS EXAMPLES
+.sp
+Unicast examples
+.INDENT 0.0
+.TP
+.B ::
+ibroute 4 # dump all lids with valid out ports of switch with lid 4
+ibroute \-a 4 # same, but dump all lids, even with invalid out ports
+ibroute \-n 4 # simple dump format \- no destination resolution
+ibroute 4 10 # dump lids starting from 10 (up to FDBTop)
+ibroute 4 0x10 0x20 # dump lid range
+ibroute \-G 0x08f1040023 # resolve switch by GUID
+ibroute \-D 0,1 # resolve switch by direct path
+.UNINDENT
+.sp
+Multicast examples
+.INDENT 0.0
+.TP
+.B ::
+ibroute \-M 4 # dump all non empty mlids of switch with lid 4
+ibroute \-M 4 0xc010 0xc020 # same, but with range
+ibroute \-M \-n 4 # simple dump format
+.UNINDENT
+.SS SEE ALSO
+.sp
+ibtracert (8)
+.SS AUTHOR
+.INDENT 0.0
+.TP
+.B Hal Rosenstock
+< \fI\%halr@voltaire.com\fP >
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/contrib/ofed/infiniband-diags/man/ibrouters.8 b/contrib/ofed/infiniband-diags/man/ibrouters.8
new file mode 100644
index 000000000000..80530c6ee396
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/man/ibrouters.8
@@ -0,0 +1,184 @@
+.\" Man page generated from reStructuredText.
+.
+.TH IBROUTERS 8 "" "" "OpenIB Diagnostics"
+.SH NAME
+IBROUTERS \- show InfiniBand router nodes in topology
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.SH SYNOPSIS
+.sp
+ibrouters [options] [<topology\-file>]
+.SH DESCRIPTION
+.sp
+ibrouters is a script which either walks the IB subnet topology or uses an
+already saved topology file and extracts the router nodes.
+.SH OPTIONS
+.\" Define the common option -C
+.
+.sp
+\fB\-C, \-\-Ca <ca_name>\fP use the specified ca_name.
+.\" Define the common option -P
+.
+.sp
+\fB\-P, \-\-Port <ca_port>\fP use the specified ca_port.
+.\" Define the common option -t
+.
+.sp
+\fB\-t, \-\-timeout <timeout_ms>\fP override the default timeout for the solicited mads.
+.\" Define the common option -y
+.
+.INDENT 0.0
+.TP
+.B \fB\-y, \-\-m_key <key>\fP
+use the specified M_key for requests. If non\-numeric value (like \(aqx\(aq)
+is specified then a value will be prompted for.
+.UNINDENT
+.\" Define the common option -h
+.
+.sp
+\fB\-h, \-\-help\fP show the usage message
+.\" Define the common option -z
+.
+.sp
+\fB\-\-config, \-z <config_file>\fP Specify alternate config file.
+.INDENT 0.0
+.INDENT 3.5
+Default: /etc/infiniband-diags/ibdiag.conf
+.UNINDENT
+.UNINDENT
+.\" Explanation of local port selection
+.
+.SS Local port Selection
+.sp
+Multiple port/Multiple CA support: when no IB device or port is specified
+(see the "local umad parameters" below), the libibumad library
+selects the port to use by the following criteria:
+.INDENT 0.0
+.INDENT 3.5
+.INDENT 0.0
+.IP 1. 3
+the first port that is ACTIVE.
+.IP 2. 3
+if not found, the first port that is UP (physical link up).
+.UNINDENT
+.sp
+If a port and/or CA name is specified, the libibumad library attempts
+to fulfill the user request, and will fail if it is not possible.
+.sp
+For example:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+ibaddr # use the first port (criteria #1 above)
+ibaddr \-C mthca1 # pick the best port from "mthca1" only.
+ibaddr \-P 2 # use the second (active/up) port from the first available IB device.
+ibaddr \-C mthca0 \-P 2 # use the specified port only.
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SH FILES
+.\" Common text for the config file
+.
+.SS CONFIG FILE
+.sp
+/etc/infiniband-diags/ibdiag.conf
+.sp
+A global config file is provided to set some of the common options for all
+tools. See supplied config file for details.
+.\" Common text to describe the node name map file.
+.
+.SS NODE NAME MAP FILE FORMAT
+.sp
+The node name map is used to specify user friendly names for nodes in the
+output. GUIDs are used to perform the lookup.
+.sp
+This functionality is provided by the opensm\-libs package. See \fBopensm(8)\fP
+for the file location for your installation.
+.sp
+\fBGenerically:\fP
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+# comment
+<guid> "<name>"
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+\fBExample:\fP
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+# IB1
+# Line cards
+0x0008f104003f125c "IB1 (Rack 11 slot 1 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f125d "IB1 (Rack 11 slot 1 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f10d2 "IB1 (Rack 11 slot 2 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f10d3 "IB1 (Rack 11 slot 2 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f10bf "IB1 (Rack 11 slot 12 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+
+# Spines
+0x0008f10400400e2d "IB1 (Rack 11 spine 1 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e2e "IB1 (Rack 11 spine 1 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e2f "IB1 (Rack 11 spine 1 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e31 "IB1 (Rack 11 spine 2 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e32 "IB1 (Rack 11 spine 2 ) ISR9288 Voltaire sFB\-12D"
+
+# GUID Node Name
+0x0008f10400411a08 "SW1 (Rack 3) ISR9024 Voltaire 9024D"
+0x0008f10400411a28 "SW2 (Rack 3) ISR9024 Voltaire 9024D"
+0x0008f10400411a34 "SW3 (Rack 3) ISR9024 Voltaire 9024D"
+0x0008f104004119d0 "SW4 (Rack 3) ISR9024 Voltaire 9024D"
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SH SEE ALSO
+.sp
+ibnetdiscover(8)
+.SH DEPENDENCIES
+.sp
+ibnetdiscover, ibnetdiscover format
+.SH AUTHOR
+.INDENT 0.0
+.TP
+.B Hal Rosenstock
+< \fI\%halr@voltaire.com\fP >
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/contrib/ofed/infiniband-diags/man/ibstat.8 b/contrib/ofed/infiniband-diags/man/ibstat.8
new file mode 100644
index 000000000000..4ce3cc8a5221
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/man/ibstat.8
@@ -0,0 +1,118 @@
+.\" Man page generated from reStructuredText.
+.
+.TH IBSTAT 8 "" "" "Open IB Diagnostics"
+.SH NAME
+IBSTAT \-
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.SH QUERY BASIC STATUS OF INFINIBAND DEVICE(S)
+.SS SYNOPSIS
+.sp
+ibstat [options] <ca_name> [portnum]
+.SS DESCRIPTION
+.sp
+ibstat is a binary which displays basic information obtained from the local
+IB driver. Output includes LID, SMLID, port state, link width active, and port
+physical state.
+.sp
+It is similar to the ibstatus utility but implemented as a binary rather
+than a script. It has options to list CAs and/or ports and displays more
+information than ibstatus.
+.SS OPTIONS
+.INDENT 0.0
+.TP
+.B \fB\-l, \-\-list_of_cas\fP
+list all IB devices
+.TP
+.B \fB\-s, \-\-short\fP
+short output
+.TP
+.B \fB\-p, \-\-port_list\fP
+show port list
+.TP
+.B \fBca_name\fP
+InfiniBand device name
+.TP
+.B \fBportnum\fP
+port number of InfiniBand device
+.UNINDENT
+.SS Debugging flags
+.\" Define the common option -d
+.
+.INDENT 0.0
+.TP
+.B \-d
+raise the IB debugging level.
+May be used several times (\-ddd or \-d \-d \-d).
+.UNINDENT
+.\" Define the common option -h
+.
+.sp
+\fB\-h, \-\-help\fP show the usage message
+.\" Define the common option -v
+.
+.INDENT 0.0
+.TP
+.B \fB\-v, \-\-verbose\fP
+increase the application verbosity level.
+May be used several times (\-vv or \-v \-v \-v)
+.UNINDENT
+.\" Define the common option -V
+.
+.sp
+\fB\-V, \-\-version\fP show the version info.
+.SS Configuration flags
+.\" Define the common option -z
+.
+.sp
+\fB\-\-config, \-z <config_file>\fP Specify alternate config file.
+.INDENT 0.0
+.INDENT 3.5
+Default: /etc/infiniband-diags/ibdiag.conf
+.UNINDENT
+.UNINDENT
+.SS EXAMPLES
+.INDENT 0.0
+.TP
+.B ::
+ibstat # display status of all ports on all IB devices
+ibstat \-l # list all IB devices
+ibstat \-p # show port guids
+ibstat mthca0 2 # show status of port 2 of \(aqmthca0\(aq
+.UNINDENT
+.SS SEE ALSO
+.sp
+ibstatus (8)
+.SS AUTHOR
+.INDENT 0.0
+.TP
+.B Hal Rosenstock
+< \fI\%halr@voltaire.com\fP >
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/contrib/ofed/infiniband-diags/man/ibstatus.8 b/contrib/ofed/infiniband-diags/man/ibstatus.8
new file mode 100644
index 000000000000..dcfd2691e6d8
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/man/ibstatus.8
@@ -0,0 +1,73 @@
+.\" Man page generated from reStructuredText.
+.
+.TH IBSTATUS 8 "" "" "Open IB Diagnostics"
+.SH NAME
+IBSTATUS \-
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.SH QUERY BASIC STATUS OF INFINIBAND DEVICE(S)
+.SS SYNOPSIS
+.sp
+ibstatus [\-h] [devname[:port]]...
+.SS DESCRIPTION
+.sp
+ibstatus is a script which displays basic information obtained from the local
+IB driver. Output includes LID, SMLID, port state, link width active, and port
+physical state.
+.SS OPTIONS
+.\" Define the common option -h
+.
+.sp
+\fB\-h, \-\-help\fP show the usage message
+.INDENT 0.0
+.TP
+.B \fBdevname\fP
+InfiniBand device name
+.TP
+.B \fBportnum\fP
+port number of InfiniBand device
+.UNINDENT
+.SS EXAMPLES
+.INDENT 0.0
+.TP
+.B ::
+ibstatus # display status of all IB ports
+ibstatus mthca1 # status of mthca1 ports
+ibstatus mthca1:1 mthca0:2 # show status of specified ports
+.UNINDENT
+.SS SEE ALSO
+.sp
+\fBibstat (8)\fP
+.SS AUTHOR
+.INDENT 0.0
+.TP
+.B Hal Rosenstock
+< \fI\%halr@voltaire.com\fP >
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/contrib/ofed/infiniband-diags/man/ibswitches.8 b/contrib/ofed/infiniband-diags/man/ibswitches.8
new file mode 100644
index 000000000000..39f3041abc85
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/man/ibswitches.8
@@ -0,0 +1,184 @@
+.\" Man page generated from reStructuredText.
+.
+.TH IBSWITCHES 8 "" "" "OpenIB Diagnostics"
+.SH NAME
+IBSWITCHES \- show InfiniBand switch nodes in topology
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.SH SYNOPSIS
+.sp
+ibswitches [options] [<topology\-file>]
+.SH DESCRIPTION
+.sp
+ibswitches is a script which either walks the IB subnet topology or uses an
+already saved topology file and extracts the switch nodes.
+.SH OPTIONS
+.\" Define the common option -C
+.
+.sp
+\fB\-C, \-\-Ca <ca_name>\fP use the specified ca_name.
+.\" Define the common option -P
+.
+.sp
+\fB\-P, \-\-Port <ca_port>\fP use the specified ca_port.
+.\" Define the common option -t
+.
+.sp
+\fB\-t, \-\-timeout <timeout_ms>\fP override the default timeout for the solicited mads.
+.\" Define the common option -y
+.
+.INDENT 0.0
+.TP
+.B \fB\-y, \-\-m_key <key>\fP
+use the specified M_key for requests. If non\-numeric value (like \(aqx\(aq)
+is specified then a value will be prompted for.
+.UNINDENT
+.\" Define the common option -h
+.
+.sp
+\fB\-h, \-\-help\fP show the usage message
+.\" Define the common option -z
+.
+.sp
+\fB\-\-config, \-z <config_file>\fP Specify alternate config file.
+.INDENT 0.0
+.INDENT 3.5
+Default: /etc/infiniband-diags/ibdiag.conf
+.UNINDENT
+.UNINDENT
+.\" Explanation of local port selection
+.
+.SS Local port Selection
+.sp
+Multiple port/Multiple CA support: when no IB device or port is specified
+(see the "local umad parameters" below), the libibumad library
+selects the port to use by the following criteria:
+.INDENT 0.0
+.INDENT 3.5
+.INDENT 0.0
+.IP 1. 3
+the first port that is ACTIVE.
+.IP 2. 3
+if not found, the first port that is UP (physical link up).
+.UNINDENT
+.sp
+If a port and/or CA name is specified, the libibumad library attempts
+to fulfill the user request, and will fail if it is not possible.
+.sp
+For example:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+ibaddr # use the first port (criteria #1 above)
+ibaddr \-C mthca1 # pick the best port from "mthca1" only.
+ibaddr \-P 2 # use the second (active/up) port from the first available IB device.
+ibaddr \-C mthca0 \-P 2 # use the specified port only.
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SH FILES
+.\" Common text for the config file
+.
+.SS CONFIG FILE
+.sp
+/etc/infiniband-diags/ibdiag.conf
+.sp
+A global config file is provided to set some of the common options for all
+tools. See supplied config file for details.
+.\" Common text to describe the node name map file.
+.
+.SS NODE NAME MAP FILE FORMAT
+.sp
+The node name map is used to specify user friendly names for nodes in the
+output. GUIDs are used to perform the lookup.
+.sp
+This functionality is provided by the opensm\-libs package. See \fBopensm(8)\fP
+for the file location for your installation.
+.sp
+\fBGenerically:\fP
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+# comment
+<guid> "<name>"
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+\fBExample:\fP
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+# IB1
+# Line cards
+0x0008f104003f125c "IB1 (Rack 11 slot 1 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f125d "IB1 (Rack 11 slot 1 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f10d2 "IB1 (Rack 11 slot 2 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f10d3 "IB1 (Rack 11 slot 2 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f10bf "IB1 (Rack 11 slot 12 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+
+# Spines
+0x0008f10400400e2d "IB1 (Rack 11 spine 1 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e2e "IB1 (Rack 11 spine 1 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e2f "IB1 (Rack 11 spine 1 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e31 "IB1 (Rack 11 spine 2 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e32 "IB1 (Rack 11 spine 2 ) ISR9288 Voltaire sFB\-12D"
+
+# GUID Node Name
+0x0008f10400411a08 "SW1 (Rack 3) ISR9024 Voltaire 9024D"
+0x0008f10400411a28 "SW2 (Rack 3) ISR9024 Voltaire 9024D"
+0x0008f10400411a34 "SW3 (Rack 3) ISR9024 Voltaire 9024D"
+0x0008f104004119d0 "SW4 (Rack 3) ISR9024 Voltaire 9024D"
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SH SEE ALSO
+.sp
+ibnetdiscover(8)
+.SH DEPENDENCIES
+.sp
+ibnetdiscover, ibnetdiscover format
+.SH AUTHOR
+.INDENT 0.0
+.TP
+.B Hal Rosenstock
+< \fI\%halr@voltaire.com\fP >
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/contrib/ofed/infiniband-diags/man/ibsysstat.8 b/contrib/ofed/infiniband-diags/man/ibsysstat.8
new file mode 100644
index 000000000000..126be4ec9dde
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/man/ibsysstat.8
@@ -0,0 +1,188 @@
+.\" Man page generated from reStructuredText.
+.
+.TH IBSYSSTAT 8 "" "" "Open IB Diagnostics"
+.SH NAME
+IBSYSSTAT \-
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.SH SYSTEM STATUS ON AN INFINIBAND ADDRESS
+.SS SYNOPSIS
+.sp
+ibsysstat [options] <dest lid | guid> [<op>]
+.SS DESCRIPTION
+.sp
+ibsysstat uses vendor mads to validate connectivity between IB nodes
+and obtain other information about the IB node. ibsysstat is run as
+client/server. Default is to run as client.
+.SS OPTIONS
+.sp
+Current supported operations:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+ping \e\- verify connectivity to server (default)
+host \e\- obtain host information from server
+cpu \e\- obtain cpu information from server
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \fB\-o, \-\-oui\fP
+use specified OUI number to multiplex vendor mads
+.TP
+.B \fB\-S, \-\-Server\fP
+start in server mode (do not return)
+.TP
+.B .sp
+\fB\-\-dgid <gid>\fP
+destination GID: use when GRH is required in packets (IPv6 format)
+.UNINDENT
+.SS Addressing Flags
+.\" Define the common option -G
+.
+.sp
+\fB\-G, \-\-Guid\fP The address specified is a Port GUID
+.\" Define the common option -L
+.
+.sp
+\fB\-L, \-\-Lid\fP The address specified is a LID
+.\" Define the common option -s
+.
+.sp
+\fB\-s, \-\-sm_port <smlid>\fP use \(aqsmlid\(aq as the target lid for SA queries.
+.SS Port Selection flags
+.\" Define the common option -C
+.
+.sp
+\fB\-C, \-\-Ca <ca_name>\fP use the specified ca_name.
+.\" Define the common option -P
+.
+.sp
+\fB\-P, \-\-Port <ca_port>\fP use the specified ca_port.
+.\" Explanation of local port selection
+.
+.SS Local port Selection
+.sp
+Multiple port/Multiple CA support: when no IB device or port is specified
+(see the "local umad parameters" below), the libibumad library
+selects the port to use by the following criteria:
+.INDENT 0.0
+.INDENT 3.5
+.INDENT 0.0
+.IP 1. 3
+the first port that is ACTIVE.
+.IP 2. 3
+if not found, the first port that is UP (physical link up).
+.UNINDENT
+.sp
+If a port and/or CA name is specified, the libibumad library attempts
+to fulfill the user request, and will fail if it is not possible.
+.sp
+For example:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+ibaddr # use the first port (criteria #1 above)
+ibaddr \-C mthca1 # pick the best port from "mthca1" only.
+ibaddr \-P 2 # use the second (active/up) port from the first available IB device.
+ibaddr \-C mthca0 \-P 2 # use the specified port only.
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS Debugging flags
+.\" Define the common option -d
+.
+.INDENT 0.0
+.TP
+.B \-d
+raise the IB debugging level.
+May be used several times (\-ddd or \-d \-d \-d).
+.UNINDENT
+.\" Define the common option -e
+.
+.INDENT 0.0
+.TP
+.B \-e
+show send and receive errors (timeouts and others)
+.UNINDENT
+.\" Define the common option -h
+.
+.sp
+\fB\-h, \-\-help\fP show the usage message
+.\" Define the common option -v
+.
+.INDENT 0.0
+.TP
+.B \fB\-v, \-\-verbose\fP
+increase the application verbosity level.
+May be used several times (\-vv or \-v \-v \-v)
+.UNINDENT
+.\" Define the common option -V
+.
+.sp
+\fB\-V, \-\-version\fP show the version info.
+.SS Configuration flags
+.\" Define the common option -t
+.
+.sp
+\fB\-t, \-\-timeout <timeout_ms>\fP override the default timeout for the solicited mads.
+.\" Define the common option -z
+.
+.sp
+\fB\-\-config, \-z <config_file>\fP Specify alternate config file.
+.INDENT 0.0
+.INDENT 3.5
+Default: /etc/infiniband-diags/ibdiag.conf
+.UNINDENT
+.UNINDENT
+.SS FILES
+.\" Common text for the config file
+.
+.SS CONFIG FILE
+.sp
+/etc/infiniband-diags/ibdiag.conf
+.sp
+A global config file is provided to set some of the common options for all
+tools. See supplied config file for details.
+.SS AUTHOR
+.INDENT 0.0
+.TP
+.B Hal Rosenstock
+< \fI\%halr@voltaire.com\fP >
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/contrib/ofed/infiniband-diags/man/ibtracert.8 b/contrib/ofed/infiniband-diags/man/ibtracert.8
new file mode 100644
index 000000000000..21ad34054078
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/man/ibtracert.8
@@ -0,0 +1,268 @@
+.\" Man page generated from reStructuredText.
+.
+.TH IBTRACERT 8 "" "" "Open IB Diagnostics"
+.SH NAME
+IBTRACERT \-
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.SH TRACE INFINIBAND PATH
+.SS SYNOPSIS
+.sp
+ibtracert [options] [<lid|guid> [<startlid> [<endlid>]]]
+.SS DESCRIPTION
+.sp
+ibtracert uses SMPs to trace the path from a source GID/LID to a
+destination GID/LID. Each hop along the path is displayed until
+the destination is reached or a hop does not respond. By using
+the \-m option, multicast path tracing can be performed between source
+and destination nodes.
+.SS OPTIONS
+.INDENT 0.0
+.TP
+.B \fB\-n, \-\-no_info\fP
+simple format; don\(aqt show additional information
+.TP
+.B \fB\-m\fP
+show the multicast trace of the specified mlid
+.TP
+.B \fB\-f, \-\-force\fP
+force route to destination port
+.UNINDENT
+.SS Addressing Flags
+.\" Define the common option -G
+.
+.sp
+\fB\-G, \-\-Guid\fP The address specified is a Port GUID
+.\" Define the common option -L
+.
+.sp
+\fB\-L, \-\-Lid\fP The address specified is a LID
+.\" Define the common option -s
+.
+.sp
+\fB\-s, \-\-sm_port <smlid>\fP use \(aqsmlid\(aq as the target lid for SA queries.
+.SS Port Selection flags
+.\" Define the common option -C
+.
+.sp
+\fB\-C, \-\-Ca <ca_name>\fP use the specified ca_name.
+.\" Define the common option -P
+.
+.sp
+\fB\-P, \-\-Port <ca_port>\fP use the specified ca_port.
+.\" Explanation of local port selection
+.
+.SS Local port Selection
+.sp
+Multiple port/Multiple CA support: when no IB device or port is specified
+(see the "local umad parameters" below), the libibumad library
+selects the port to use by the following criteria:
+.INDENT 0.0
+.INDENT 3.5
+.INDENT 0.0
+.IP 1. 3
+the first port that is ACTIVE.
+.IP 2. 3
+if not found, the first port that is UP (physical link up).
+.UNINDENT
+.sp
+If a port and/or CA name is specified, the libibumad library attempts
+to fulfill the user request, and will fail if it is not possible.
+.sp
+For example:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+ibaddr # use the first port (criteria #1 above)
+ibaddr \-C mthca1 # pick the best port from "mthca1" only.
+ibaddr \-P 2 # use the second (active/up) port from the first available IB device.
+ibaddr \-C mthca0 \-P 2 # use the specified port only.
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS Debugging flags
+.\" Define the common option -d
+.
+.INDENT 0.0
+.TP
+.B \-d
+raise the IB debugging level.
+May be used several times (\-ddd or \-d \-d \-d).
+.UNINDENT
+.\" Define the common option -e
+.
+.INDENT 0.0
+.TP
+.B \-e
+show send and receive errors (timeouts and others)
+.UNINDENT
+.\" Define the common option -h
+.
+.sp
+\fB\-h, \-\-help\fP show the usage message
+.\" Define the common option -v
+.
+.INDENT 0.0
+.TP
+.B \fB\-v, \-\-verbose\fP
+increase the application verbosity level.
+May be used several times (\-vv or \-v \-v \-v)
+.UNINDENT
+.\" Define the common option -V
+.
+.sp
+\fB\-V, \-\-version\fP show the version info.
+.SS Configuration flags
+.\" Define the common option -t
+.
+.sp
+\fB\-t, \-\-timeout <timeout_ms>\fP override the default timeout for the solicited mads.
+.\" Define the common option --node-name-map
+.
+.sp
+\fB\-\-node\-name\-map <node\-name\-map>\fP Specify a node name map.
+.INDENT 0.0
+.INDENT 3.5
+This file maps GUIDs to more user friendly names. See FILES section.
+.UNINDENT
+.UNINDENT
+.\" Define the common option -y
+.
+.INDENT 0.0
+.TP
+.B \fB\-y, \-\-m_key <key>\fP
+use the specified M_key for requests. If non\-numeric value (like \(aqx\(aq)
+is specified then a value will be prompted for.
+.UNINDENT
+.\" Define the common option -z
+.
+.sp
+\fB\-\-config, \-z <config_file>\fP Specify alternate config file.
+.INDENT 0.0
+.INDENT 3.5
+Default: /etc/infiniband-diags/ibdiag.conf
+.UNINDENT
+.UNINDENT
+.SS FILES
+.\" Common text for the config file
+.
+.SS CONFIG FILE
+.sp
+/etc/infiniband-diags/ibdiag.conf
+.sp
+A global config file is provided to set some of the common options for all
+tools. See supplied config file for details.
+.\" Common text to describe the node name map file.
+.
+.SS NODE NAME MAP FILE FORMAT
+.sp
+The node name map is used to specify user friendly names for nodes in the
+output. GUIDs are used to perform the lookup.
+.sp
+This functionality is provided by the opensm\-libs package. See \fBopensm(8)\fP
+for the file location for your installation.
+.sp
+\fBGenerically:\fP
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+# comment
+<guid> "<name>"
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+\fBExample:\fP
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+# IB1
+# Line cards
+0x0008f104003f125c "IB1 (Rack 11 slot 1 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f125d "IB1 (Rack 11 slot 1 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f10d2 "IB1 (Rack 11 slot 2 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f10d3 "IB1 (Rack 11 slot 2 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f10bf "IB1 (Rack 11 slot 12 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+
+# Spines
+0x0008f10400400e2d "IB1 (Rack 11 spine 1 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e2e "IB1 (Rack 11 spine 1 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e2f "IB1 (Rack 11 spine 1 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e31 "IB1 (Rack 11 spine 2 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e32 "IB1 (Rack 11 spine 2 ) ISR9288 Voltaire sFB\-12D"
+
+# GUID Node Name
+0x0008f10400411a08 "SW1 (Rack 3) ISR9024 Voltaire 9024D"
+0x0008f10400411a28 "SW2 (Rack 3) ISR9024 Voltaire 9024D"
+0x0008f10400411a34 "SW3 (Rack 3) ISR9024 Voltaire 9024D"
+0x0008f104004119d0 "SW4 (Rack 3) ISR9024 Voltaire 9024D"
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SS EXAMPLES
+.sp
+Unicast examples
+.INDENT 0.0
+.TP
+.B ::
+ibtracert 4 16 # show path between lids 4 and 16
+ibtracert \-n 4 16 # same, but using simple output format
+ibtracert \-G 0x8f1040396522d 0x002c9000100d051 # use guid addresses
+.UNINDENT
+.sp
+Multicast example
+.INDENT 0.0
+.TP
+.B ::
+ibtracert \-m 0xc000 4 16 # show multicast path of mlid 0xc000 between lids 4 and 16
+.UNINDENT
+.SS SEE ALSO
+.sp
+ibroute (8)
+.SS AUTHOR
+.INDENT 0.0
+.TP
+.B Hal Rosenstock
+<\fI\%hal.rosenstock@gmail.com\fP>
+.TP
+.B Ira Weiny
+< \fI\%ira.weiny@intel.com\fP >
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/contrib/ofed/infiniband-diags/man/infiniband-diags.8 b/contrib/ofed/infiniband-diags/man/infiniband-diags.8
new file mode 100644
index 000000000000..d2d95c6d08ac
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/man/infiniband-diags.8
@@ -0,0 +1,452 @@
+.\" Man page generated from reStructuredText.
+.
+.TH INFINIBAND-DIAGS 8 "" "" "Open IB Diagnostics"
+.SH NAME
+INFINIBAND-DIAGS \-
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.SH DIAGNOSTICS FOR INFINIBAND FABRICS
+.SS DESCRIPTION
+.sp
+infiniband\-diags is a set of utilities designed to help configure, debug, and
+maintain infiniband fabrics. Many tools and utilities are provided. Some with
+similar functionality.
+.sp
+The base utilities use directed route MAD\(aqs to perform their operations. They
+may therefore work even in unconfigured subnets. Other, higher level
+utilities, require LID routed MAD\(aqs and to some extent SA/SM access.
+.SS THE USE OF SMPs (QP0)
+.sp
+Many of the tools in this package rely on the use of SMPs via QP0 to acquire
+data directly from the SMA. While this mode of operation is not technically in
+compliance with the InfiniBand specification, practical experience has found
+that this level of diagnostics is valuable when working with a fabric which is
+broken or only partially configured. For this reason many of these tools may
+require the use of an MKey or operation from Virtual Machines may be restricted
+for security reasons.
+.SS COMMON OPTIONS
+.sp
+Most OpenIB diagnostics take some of the following common flags. The exact list
+of supported flags per utility can be found in the documentation for those
+commands.
+.SS Addressing Flags
+.sp
+The \-D and \-G option have two forms:
+.\" Define the common option -D for Directed routes
+.
+.sp
+\fB\-D, \-\-Direct\fP The address specified is a directed route
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+Examples:
+ [options] \-D [options] "0" # self port
+ [options] \-D [options] "0,1,2,1,4" # out via port 1, then 2, ...
+
+ (Note the second number in the path specified must match the port being
+ used. This can be specified using the port selection flag \(aq\-P\(aq or the
+ port found through the automatic selection process.)
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.\" Define the common option -D for Directed routes
+.
+.sp
+\fB\-D, \-\-Direct <dr_path>\fP The address specified is a directed route
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+Examples:
+ \-D "0" # self port
+ \-D "0,1,2,1,4" # out via port 1, then 2, ...
+
+ (Note the second number in the path specified must match the port being
+ used. This can be specified using the port selection flag \(aq\-P\(aq or the
+ port found through the automatic selection process.)
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.\" Define the common option -G
+.
+.sp
+\fB\-G, \-\-Guid\fP The address specified is a Port GUID
+.\" Define the common option -G
+.
+.sp
+\fB\-\-port\-guid, \-G <port_guid>\fP Specify a port_guid
+.\" Define the common option -L
+.
+.sp
+\fB\-L, \-\-Lid\fP The address specified is a LID
+.\" Define the common option -s
+.
+.sp
+\fB\-s, \-\-sm_port <smlid>\fP use \(aqsmlid\(aq as the target lid for SA queries.
+.SS Port Selection flags
+.\" Define the common option -C
+.
+.sp
+\fB\-C, \-\-Ca <ca_name>\fP use the specified ca_name.
+.\" Define the common option -P
+.
+.sp
+\fB\-P, \-\-Port <ca_port>\fP use the specified ca_port.
+.\" Explanation of local port selection
+.
+.SS Local port Selection
+.sp
+Multiple port/Multiple CA support: when no IB device or port is specified
+(see the "local umad parameters" below), the libibumad library
+selects the port to use by the following criteria:
+.INDENT 0.0
+.INDENT 3.5
+.INDENT 0.0
+.IP 1. 3
+the first port that is ACTIVE.
+.IP 2. 3
+if not found, the first port that is UP (physical link up).
+.UNINDENT
+.sp
+If a port and/or CA name is specified, the libibumad library attempts
+to fulfill the user request, and will fail if it is not possible.
+.sp
+For example:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+ibaddr # use the first port (criteria #1 above)
+ibaddr \-C mthca1 # pick the best port from "mthca1" only.
+ibaddr \-P 2 # use the second (active/up) port from the first available IB device.
+ibaddr \-C mthca0 \-P 2 # use the specified port only.
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS Debugging flags
+.\" Define the common option -d
+.
+.INDENT 0.0
+.TP
+.B \-d
+raise the IB debugging level.
+May be used several times (\-ddd or \-d \-d \-d).
+.UNINDENT
+.\" Define the common option -e
+.
+.INDENT 0.0
+.TP
+.B \-e
+show send and receive errors (timeouts and others)
+.UNINDENT
+.\" Define the common option -h
+.
+.sp
+\fB\-h, \-\-help\fP show the usage message
+.\" Define the common option -v
+.
+.INDENT 0.0
+.TP
+.B \fB\-v, \-\-verbose\fP
+increase the application verbosity level.
+May be used several times (\-vv or \-v \-v \-v)
+.UNINDENT
+.\" Define the common option -V
+.
+.sp
+\fB\-V, \-\-version\fP show the version info.
+.SS Configuration flags
+.\" Define the common option -t
+.
+.sp
+\fB\-t, \-\-timeout <timeout_ms>\fP override the default timeout for the solicited mads.
+.\" Define the common option -z
+.
+.INDENT 0.0
+.TP
+.B \fB\-\-outstanding_smps, \-o <val>\fP
+Specify the number of outstanding SMP\(aqs which should be issued during the scan
+.sp
+Default: 2
+.UNINDENT
+.\" Define the common option --node-name-map
+.
+.sp
+\fB\-\-node\-name\-map <node\-name\-map>\fP Specify a node name map.
+.INDENT 0.0
+.INDENT 3.5
+This file maps GUIDs to more user friendly names. See FILES section.
+.UNINDENT
+.UNINDENT
+.\" Define the common option -z
+.
+.sp
+\fB\-\-config, \-z <config_file>\fP Specify alternate config file.
+.INDENT 0.0
+.INDENT 3.5
+Default: /etc/infiniband-diags/ibdiag.conf
+.UNINDENT
+.UNINDENT
+.SS COMMON FILES
+.sp
+The following config files are common amongst many of the utilities.
+.\" Common text for the config file
+.
+.SS CONFIG FILE
+.sp
+/etc/infiniband-diags/ibdiag.conf
+.sp
+A global config file is provided to set some of the common options for all
+tools. See supplied config file for details.
+.\" Common text to describe the node name map file.
+.
+.SS NODE NAME MAP FILE FORMAT
+.sp
+The node name map is used to specify user friendly names for nodes in the
+output. GUIDs are used to perform the lookup.
+.sp
+This functionality is provided by the opensm\-libs package. See \fBopensm(8)\fP
+for the file location for your installation.
+.sp
+\fBGenerically:\fP
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+# comment
+<guid> "<name>"
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+\fBExample:\fP
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+# IB1
+# Line cards
+0x0008f104003f125c "IB1 (Rack 11 slot 1 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f125d "IB1 (Rack 11 slot 1 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f10d2 "IB1 (Rack 11 slot 2 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f10d3 "IB1 (Rack 11 slot 2 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f10bf "IB1 (Rack 11 slot 12 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+
+# Spines
+0x0008f10400400e2d "IB1 (Rack 11 spine 1 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e2e "IB1 (Rack 11 spine 1 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e2f "IB1 (Rack 11 spine 1 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e31 "IB1 (Rack 11 spine 2 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e32 "IB1 (Rack 11 spine 2 ) ISR9288 Voltaire sFB\-12D"
+
+# GUID Node Name
+0x0008f10400411a08 "SW1 (Rack 3) ISR9024 Voltaire 9024D"
+0x0008f10400411a28 "SW2 (Rack 3) ISR9024 Voltaire 9024D"
+0x0008f10400411a34 "SW3 (Rack 3) ISR9024 Voltaire 9024D"
+0x0008f104004119d0 "SW4 (Rack 3) ISR9024 Voltaire 9024D"
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.\" Common text to describe the Topology file.
+.
+.SS TOPOLOGY FILE FORMAT
+.sp
+The topology file format is human readable and largely intuitive.
+Most identifiers are given textual names like vendor ID (vendid), device ID
+(device ID), GUIDs of various types (sysimgguid, caguid, switchguid, etc.).
+PortGUIDs are shown in parentheses (). For switches, this is shown on the
+switchguid line. For CA and router ports, it is shown on the connectivity
+lines. The IB node is identified followed by the number of ports and a quoted
+the node GUID. On the right of this line is a comment (#) followed by the
+NodeDescription in quotes. If the node is a switch, this line also contains
+whether switch port 0 is base or enhanced, and the LID and LMC of port 0.
+Subsequent lines pertaining to this node show the connectivity. On the
+left is the port number of the current node. On the right is the peer node
+(node at other end of link). It is identified in quotes with nodetype
+followed by \- followed by NodeGUID with the port number in square brackets.
+Further on the right is a comment (#). What follows the comment is
+dependent on the node type. If it it a switch node, it is followed by
+the NodeDescription in quotes and the LID of the peer node. If it is a
+CA or router node, it is followed by the local LID and LMC and then
+followed by the NodeDescription in quotes and the LID of the peer node.
+The active link width and speed are then appended to the end of this
+output line.
+.sp
+An example of this is:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+#
+# Topology file: generated on Tue Jun 5 14:15:10 2007
+#
+# Max of 3 hops discovered
+# Initiated from node 0008f10403960558 port 0008f10403960559
+
+Non\-Chassis Nodes
+
+vendid=0x8f1
+devid=0x5a06
+sysimgguid=0x5442ba00003000
+switchguid=0x5442ba00003080(5442ba00003080)
+Switch 24 "S\-005442ba00003080" # "ISR9024 Voltaire" base port 0 lid 6 lmc 0
+[22] "H\-0008f10403961354"[1](8f10403961355) # "MT23108 InfiniHost Mellanox Technologies" lid 4 4xSDR
+[10] "S\-0008f10400410015"[1] # "SW\-6IB4 Voltaire" lid 3 4xSDR
+[8] "H\-0008f10403960558"[2](8f1040396055a) # "MT23108 InfiniHost Mellanox Technologies" lid 14 4xSDR
+[6] "S\-0008f10400410015"[3] # "SW\-6IB4 Voltaire" lid 3 4xSDR
+[12] "H\-0008f10403960558"[1](8f10403960559) # "MT23108 InfiniHost Mellanox Technologies" lid 10 4xSDR
+
+vendid=0x8f1
+devid=0x5a05
+switchguid=0x8f10400410015(8f10400410015)
+Switch 8 "S\-0008f10400410015" # "SW\-6IB4 Voltaire" base port 0 lid 3 lmc 0
+[6] "H\-0008f10403960984"[1](8f10403960985) # "MT23108 InfiniHost Mellanox Technologies" lid 16 4xSDR
+[4] "H\-005442b100004900"[1](5442b100004901) # "MT23108 InfiniHost Mellanox Technologies" lid 12 4xSDR
+[1] "S\-005442ba00003080"[10] # "ISR9024 Voltaire" lid 6 1xSDR
+[3] "S\-005442ba00003080"[6] # "ISR9024 Voltaire" lid 6 4xSDR
+
+vendid=0x2c9
+devid=0x5a44
+caguid=0x8f10403960984
+Ca 2 "H\-0008f10403960984" # "MT23108 InfiniHost Mellanox Technologies"
+[1](8f10403960985) "S\-0008f10400410015"[6] # lid 16 lmc 1 "SW\-6IB4 Voltaire" lid 3 4xSDR
+
+vendid=0x2c9
+devid=0x5a44
+caguid=0x5442b100004900
+Ca 2 "H\-005442b100004900" # "MT23108 InfiniHost Mellanox Technologies"
+[1](5442b100004901) "S\-0008f10400410015"[4] # lid 12 lmc 1 "SW\-6IB4 Voltaire" lid 3 4xSDR
+
+vendid=0x2c9
+devid=0x5a44
+caguid=0x8f10403961354
+Ca 2 "H\-0008f10403961354" # "MT23108 InfiniHost Mellanox Technologies"
+[1](8f10403961355) "S\-005442ba00003080"[22] # lid 4 lmc 1 "ISR9024 Voltaire" lid 6 4xSDR
+
+vendid=0x2c9
+devid=0x5a44
+caguid=0x8f10403960558
+Ca 2 "H\-0008f10403960558" # "MT23108 InfiniHost Mellanox Technologies"
+[2](8f1040396055a) "S\-005442ba00003080"[8] # lid 14 lmc 1 "ISR9024 Voltaire" lid 6 4xSDR
+[1](8f10403960559) "S\-005442ba00003080"[12] # lid 10 lmc 1 "ISR9024 Voltaire" lid 6 1xSDR
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+When grouping is used, IB nodes are organized into chassis which are
+numbered. Nodes which cannot be determined to be in a chassis are
+displayed as "Non\-Chassis Nodes". External ports are also shown on the
+connectivity lines.
+.SS Utilities list
+.SS Basic fabric conectivity
+.INDENT 0.0
+.INDENT 3.5
+See: ibnetdiscover, iblinkinfo
+.UNINDENT
+.UNINDENT
+.SS Node information
+.INDENT 0.0
+.INDENT 3.5
+See: ibnodes, ibswitches, ibhosts, ibrouters
+.UNINDENT
+.UNINDENT
+.SS Port information
+.INDENT 0.0
+.INDENT 3.5
+See: ibportstate, ibaddr
+.UNINDENT
+.UNINDENT
+.SS Switch Forwarding Table info
+.INDENT 0.0
+.INDENT 3.5
+See: ibtracert, ibroute, dump_lfts, dump_mfts, check_lft_balance, ibfindnodesusing
+.UNINDENT
+.UNINDENT
+.SS Peformance counters
+.INDENT 0.0
+.INDENT 3.5
+See: ibqueryerrors, perfquery
+.UNINDENT
+.UNINDENT
+.SS Local HCA info
+.INDENT 0.0
+.INDENT 3.5
+See: ibstat, ibstatus
+.UNINDENT
+.UNINDENT
+.SS Connectivity check
+.INDENT 0.0
+.INDENT 3.5
+See: ibping, ibsysstat
+.UNINDENT
+.UNINDENT
+.SS Low level query tools
+.INDENT 0.0
+.INDENT 3.5
+See: smpquery, smpdump, saquery, sminfo
+.UNINDENT
+.UNINDENT
+.SS Fabric verification tools
+.INDENT 0.0
+.INDENT 3.5
+See: ibidsverify
+.UNINDENT
+.UNINDENT
+.SS Backwards compatibility scripts
+.sp
+The following scripts have been identified as redundant and/or lower performing
+as compared to the above scripts. They are provided as legacy scripts when
+\-\-enable\-compat\-utils is specified at build time.
+.sp
+ibcheckerrors, ibclearcounters, ibclearerrors, ibdatacounters
+ibchecknet, ibchecknode, ibcheckport, ibcheckportstate,
+ibcheckportwidth, ibcheckstate, ibcheckwidth, ibswportwatch,
+ibprintca, ibprintrt, ibprintswitch, set_nodedesc.sh
+.SS AUTHORS
+.INDENT 0.0
+.TP
+.B Ira Weiny
+< \fI\%ira.weiny@intel.com\fP >
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/contrib/ofed/infiniband-diags/man/perfquery.8 b/contrib/ofed/infiniband-diags/man/perfquery.8
new file mode 100644
index 000000000000..236ad73174f2
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/man/perfquery.8
@@ -0,0 +1,291 @@
+.\" Man page generated from reStructuredText.
+.
+.TH PERFQUERY 8 "" "" "Open IB Diagnostics"
+.SH NAME
+PERFQUERY \-
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.SH QUERY INFINIBAND PORT COUNTERS ON A SINGLE PORT
+.SS SYNOPSIS
+.sp
+perfquery [options] [<lid|guid> [[port(s)] [reset_mask]]]
+.SS DESCRIPTION
+.sp
+perfquery uses PerfMgt GMPs to obtain the PortCounters (basic performance and
+error counters), PortExtendedCounters, PortXmitDataSL, PortRcvDataSL,
+PortRcvErrorDetails, PortXmitDiscardDetails, PortExtendedSpeedsCounters, or
+PortSamplesControl from the PMA at the node/port specified. Optionally shows
+aggregated counters for all ports of node. Finally it can, reset after read,
+or just reset the counters.
+.sp
+Note: In PortCounters, PortCountersExtended, PortXmitDataSL, and PortRcvDataSL,
+components that represent Data (e.g. PortXmitData and PortRcvData) indicate
+octets divided by 4 rather than just octets.
+.sp
+Note: Inputting a port of 255 indicates an operation be performed on all ports.
+.sp
+Note: For PortCounters, ExtendedCounters, and resets, multiple ports can be
+specified by either a comma separated list or a port range. See examples below.
+.SS OPTIONS
+.INDENT 0.0
+.TP
+.B \fB\-x, \-\-extended\fP
+show extended port counters rather than (basic) port counters.
+Note that extended port counters attribute is optional.
+.TP
+.B \fB\-X, \-\-xmtsl\fP
+show transmit data SL counter. This is an optional counter for QoS.
+.TP
+.B \fB\-S, \-\-rcvsl\fP
+show receive data SL counter. This is an optional counter for QoS.
+.TP
+.B \fB\-D, \-\-xmtdisc\fP
+show transmit discard details. This is an optional counter.
+.TP
+.B \fB\-E, \-\-rcverr\fP
+show receive error details. This is an optional counter.
+.TP
+.B \fB\-D, \-\-xmtdisc\fP
+show transmit discard details. This is an optional counter.
+.TP
+.B \fB\-T, \-\-extended_speeds\fP
+show extended speeds port counters. This is an optional counter.
+.TP
+.B \fB\-\-oprcvcounters\fP
+show Rcv Counters per Op code. This is an optional counter.
+.TP
+.B \fB\-\-flowctlcounters\fP
+show flow control counters. This is an optional counter.
+.TP
+.B \fB\-\-vloppackets\fP
+show packets received per Op code per VL. This is an optional counter.
+.TP
+.B \fB\-\-vlopdata\fP
+show data received per Op code per VL. This is an optional counter.
+.TP
+.B \fB\-\-vlxmitflowctlerrors\fP
+show flow control update errors per VL. This is an optional counter.
+.TP
+.B \fB\-\-vlxmitcounters\fP
+show ticks waiting to transmit counters per VL. This is an optional counter.
+.TP
+.B \fB\-\-swportvlcong\fP
+show sw port VL congestion. This is an optional counter.
+.TP
+.B \fB\-\-rcvcc\fP
+show Rcv congestion control counters. This is an optional counter.
+.TP
+.B \fB\-\-slrcvfecn\fP
+show SL Rcv FECN counters. This is an optional counter.
+.TP
+.B \fB\-\-slrcvbecn\fP
+show SL Rcv BECN counters. This is an optional counter.
+.TP
+.B \fB\-\-xmitcc\fP
+show Xmit congestion control counters. This is an optional counter.
+.TP
+.B \fB\-\-vlxmittimecc\fP
+show VL Xmit Time congestion control counters. This is an optional counter.
+.TP
+.B \fB\-c, \-\-smplctl\fP
+show port samples control.
+.TP
+.B \fB\-a, \-\-all_ports\fP
+show aggregated counters for all ports of the destination lid, reset
+all counters for all ports, or if multiple ports are specified, aggregate
+the counters of the specified ports. If the destination lid does not support
+the AllPortSelect flag, all ports will be iterated through to emulate
+AllPortSelect behavior.
+.TP
+.B \fB\-l, \-\-loop_ports\fP
+If all ports are selected by the user (either through the \fB\-a\fP option
+or port 255) or multiple ports are specified iterate through each port rather
+than doing than aggregate operation.
+.TP
+.B \fB\-r, \-\-reset_after_read\fP
+reset counters after read
+.TP
+.B \fB\-R, \-\-Reset_only\fP
+only reset counters
+.TP
+.B \fB\-\-dgid <gid>\fP
+destination GID: use when GRH is required in packets (IPv6 format)
+.UNINDENT
+.SS Addressing Flags
+.\" Define the common option -G
+.
+.sp
+\fB\-G, \-\-Guid\fP The address specified is a Port GUID
+.\" Define the common option -L
+.
+.sp
+\fB\-L, \-\-Lid\fP The address specified is a LID
+.\" Define the common option -s
+.
+.sp
+\fB\-s, \-\-sm_port <smlid>\fP use \(aqsmlid\(aq as the target lid for SA queries.
+.SS Port Selection flags
+.\" Define the common option -C
+.
+.sp
+\fB\-C, \-\-Ca <ca_name>\fP use the specified ca_name.
+.\" Define the common option -P
+.
+.sp
+\fB\-P, \-\-Port <ca_port>\fP use the specified ca_port.
+.\" Explanation of local port selection
+.
+.SS Local port Selection
+.sp
+Multiple port/Multiple CA support: when no IB device or port is specified
+(see the "local umad parameters" below), the libibumad library
+selects the port to use by the following criteria:
+.INDENT 0.0
+.INDENT 3.5
+.INDENT 0.0
+.IP 1. 3
+the first port that is ACTIVE.
+.IP 2. 3
+if not found, the first port that is UP (physical link up).
+.UNINDENT
+.sp
+If a port and/or CA name is specified, the libibumad library attempts
+to fulfill the user request, and will fail if it is not possible.
+.sp
+For example:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+ibaddr # use the first port (criteria #1 above)
+ibaddr \-C mthca1 # pick the best port from "mthca1" only.
+ibaddr \-P 2 # use the second (active/up) port from the first available IB device.
+ibaddr \-C mthca0 \-P 2 # use the specified port only.
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS Debugging flags
+.\" Define the common option -d
+.
+.INDENT 0.0
+.TP
+.B \-d
+raise the IB debugging level.
+May be used several times (\-ddd or \-d \-d \-d).
+.UNINDENT
+.\" Define the common option -e
+.
+.INDENT 0.0
+.TP
+.B \-e
+show send and receive errors (timeouts and others)
+.UNINDENT
+.\" Define the common option -h
+.
+.sp
+\fB\-h, \-\-help\fP show the usage message
+.\" Define the common option -v
+.
+.INDENT 0.0
+.TP
+.B \fB\-v, \-\-verbose\fP
+increase the application verbosity level.
+May be used several times (\-vv or \-v \-v \-v)
+.UNINDENT
+.\" Define the common option -V
+.
+.sp
+\fB\-V, \-\-version\fP show the version info.
+.SS Configuration flags
+.\" Define the common option -t
+.
+.sp
+\fB\-t, \-\-timeout <timeout_ms>\fP override the default timeout for the solicited mads.
+.\" Define the common option -y
+.
+.INDENT 0.0
+.TP
+.B \fB\-y, \-\-m_key <key>\fP
+use the specified M_key for requests. If non\-numeric value (like \(aqx\(aq)
+is specified then a value will be prompted for.
+.UNINDENT
+.\" Define the common option -z
+.
+.sp
+\fB\-\-config, \-z <config_file>\fP Specify alternate config file.
+.INDENT 0.0
+.INDENT 3.5
+Default: /etc/infiniband-diags/ibdiag.conf
+.UNINDENT
+.UNINDENT
+.SS FILES
+.\" Common text for the config file
+.
+.SS CONFIG FILE
+.sp
+/etc/infiniband-diags/ibdiag.conf
+.sp
+A global config file is provided to set some of the common options for all
+tools. See supplied config file for details.
+.SS EXAMPLES
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+perfquery # read local port performance counters
+perfquery 32 1 # read performance counters from lid 32, port 1
+perfquery \-x 32 1 # read extended performance counters from lid 32, port 1
+perfquery \-a 32 # read perf counters from lid 32, all ports
+perfquery \-r 32 1 # read performance counters and reset
+perfquery \-x \-r 32 1 # read extended performance counters and reset
+perfquery \-R 0x20 1 # reset performance counters of port 1 only
+perfquery \-x \-R 0x20 1 # reset extended performance counters of port 1 only
+perfquery \-R \-a 32 # reset performance counters of all ports
+perfquery \-R 32 2 0x0fff # reset only error counters of port 2
+perfquery \-R 32 2 0xf000 # reset only non\-error counters of port 2
+perfquery \-a 32 1\-10 # read performance counters from lid 32, port 1\-10, aggregate output
+perfquery \-l 32 1\-10 # read performance counters from lid 32, port 1\-10, output each port
+perfquery \-a 32 1,4,8 # read performance counters from lid 32, port 1, 4, and 8, aggregate output
+perfquery \-l 32 1,4,8 # read performance counters from lid 32, port 1, 4, and 8, output each port
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SS AUTHOR
+.INDENT 0.0
+.TP
+.B Hal Rosenstock
+< \fI\%hal.rosenstock@gmail.com\fP >
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/contrib/ofed/infiniband-diags/man/saquery.8 b/contrib/ofed/infiniband-diags/man/saquery.8
new file mode 100644
index 000000000000..82f20f7ddbc1
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/man/saquery.8
@@ -0,0 +1,380 @@
+.\" Man page generated from reStructuredText.
+.
+.TH SAQUERY 8 "" "" "Open IB Diagnostics"
+.SH NAME
+SAQUERY \-
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.SH QUERY INFINIBAND SUBNET ADMINISTRATION ATTRIBUTES
+.SS SYNOPSIS
+.sp
+saquery [options] [<name> | <lid> | <guid>]
+.SS DESCRIPTION
+.sp
+saquery issues the selected SA query. Node records are queried by default.
+.SS OPTIONS
+.INDENT 0.0
+.TP
+.B \fB\-p\fP
+get PathRecord info
+.TP
+.B \fB\-N\fP
+get NodeRecord info
+.TP
+.B \fB\-D, \-\-list\fP
+get NodeDescriptions of CAs only
+.TP
+.B \fB\-S\fP
+get ServiceRecord info
+.TP
+.B \fB\-I\fP
+get InformInfoRecord (subscription) info
+.TP
+.B \fB\-L\fP
+return the Lids of the name specified
+.TP
+.B \fB\-l\fP
+return the unique Lid of the name specified
+.TP
+.B \fB\-G\fP
+return the Guids of the name specified
+.TP
+.B \fB\-O\fP
+return the name for the Lid specified
+.TP
+.B \fB\-U\fP
+return the name for the Guid specified
+.TP
+.B \fB\-c\fP
+get the SA\(aqs class port info
+.TP
+.B \fB\-s\fP
+return the PortInfoRecords with isSM or isSMdisabled capability mask bit on
+.TP
+.B \fB\-g\fP
+get multicast group info
+.TP
+.B \fB\-m\fP
+get multicast member info. If a group is specified, limit the output
+to the group specified and print one line containing only the GUID and
+node description for each entry. Example: saquery \-m 0xc000
+.TP
+.B \fB\-x\fP
+get LinkRecord info
+.TP
+.B \fB\-\-src\-to\-dst <src:dst>\fP
+get a PathRecord for <src:dst>
+where src and dst are either node names or LIDs
+.TP
+.B \fB\-\-sgid\-to\-dgid <sgid:dgid>\fP
+get a PathRecord for \fBsgid\fP to \fBdgid\fP
+where both GIDs are in an IPv6 format acceptable to \fBinet_pton (3)\fP
+.TP
+.B \fB\-\-smkey <val>\fP
+use SM_Key value for the query. Will be used only with "trusted"
+queries. If non\-numeric value (like \(aqx\(aq) is specified then saquery
+will prompt for a value.
+Default (when not specified here or in
+/etc/infiniband-diags/ibdiag.conf) is to use SM_Key == 0 (or
+"untrusted")
+.TP
+.B \fB\-\-sa-dgid <gid>\fP
+Set the destination GID (in IPv6 format) of the SA in the GRH of the request.
+Either the actual SM GID or the SA well known GID (0::2) can be used to include
+in the GRH of the SA queries.
+.UNINDENT
+.\" Define the common option -K
+.
+.INDENT 0.0
+.TP
+.B \fB\-K, \-\-show_keys\fP
+show security keys (mkey, smkey, etc.) associated with the request.
+.UNINDENT
+.sp
+\fB\-\-slid <lid>\fP Source LID (PathRecord)
+.sp
+\fB\-\-dlid <lid>\fP Destination LID (PathRecord)
+.sp
+\fB\-\-mlid <lid>\fP Multicast LID (MCMemberRecord)
+.sp
+\fB\-\-sgid <gid>\fP Source GID (IPv6 format) (PathRecord)
+.sp
+\fB\-\-dgid <gid>\fP Destination GID (IPv6 format) (PathRecord)
+.sp
+\fB\-\-gid <gid>\fP Port GID (MCMemberRecord)
+.sp
+\fB\-\-mgid <gid>\fP Multicast GID (MCMemberRecord)
+.sp
+\fB\-\-reversible\fP Reversible path (PathRecord)
+.sp
+\fB\-\-numb_path\fP Number of paths (PathRecord)
+.INDENT 0.0
+.TP
+.B \fB\-\-pkey\fP P_Key (PathRecord, MCMemberRecord). If non\-numeric value (like \(aqx\(aq)
+is specified then saquery will prompt for a value
+.UNINDENT
+.sp
+\fB\-\-qos_class\fP QoS Class (PathRecord)
+.sp
+\fB\-\-sl\fP Service level (PathRecord, MCMemberRecord)
+.sp
+\fB\-\-mtu\fP MTU and selector (PathRecord, MCMemberRecord)
+.sp
+\fB\-\-rate\fP Rate and selector (PathRecord, MCMemberRecord)
+.sp
+\fB\-\-pkt_lifetime\fP Packet lifetime and selector (PathRecord, MCMemberRecord)
+.INDENT 0.0
+.TP
+.B \fB\-\-qkey\fP Q_Key (MCMemberRecord). If non\-numeric value (like \(aqx\(aq) is specified
+then saquery will prompt for a value
+.UNINDENT
+.sp
+\fB\-\-tclass\fP Traffic Class (PathRecord, MCMemberRecord)
+.sp
+\fB\-\-flow_label\fP Flow Label (PathRecord, MCMemberRecord)
+.sp
+\fB\-\-hop_limit\fP Hop limit (PathRecord, MCMemberRecord)
+.sp
+\fB\-\-scope\fP Scope (MCMemberRecord)
+.sp
+\fB\-\-join_state\fP Join state (MCMemberRecord)
+.sp
+\fB\-\-proxy_join\fP Proxy join (MCMemberRecord)
+.sp
+\fB\-\-service_id\fP ServiceID (PathRecord)
+.sp
+Supported query names (and aliases):
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+ClassPortInfo (CPI)
+NodeRecord (NR) [lid]
+PortInfoRecord (PIR) [[lid]/[port]/[options]]
+SL2VLTableRecord (SL2VL) [[lid]/[in_port]/[out_port]]
+PKeyTableRecord (PKTR) [[lid]/[port]/[block]]
+VLArbitrationTableRecord (VLAR) [[lid]/[port]/[block]]
+InformInfoRecord (IIR)
+LinkRecord (LR) [[from_lid]/[from_port]] [[to_lid]/[to_port]]
+ServiceRecord (SR)
+PathRecord (PR)
+MCMemberRecord (MCMR)
+LFTRecord (LFTR) [[lid]/[block]]
+MFTRecord (MFTR) [[mlid]/[position]/[block]]
+GUIDInfoRecord (GIR) [[lid]/[block]]
+SwitchInfoRecord (SWIR) [lid]
+SMInfoRecord (SMIR) [lid]
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SS Port Selection flags
+.\" Define the common option -C
+.
+.sp
+\fB\-C, \-\-Ca <ca_name>\fP use the specified ca_name.
+.\" Define the common option -P
+.
+.sp
+\fB\-P, \-\-Port <ca_port>\fP use the specified ca_port.
+.\" Explanation of local port selection
+.
+.SS Local port Selection
+.sp
+Multiple port/Multiple CA support: when no IB device or port is specified
+(see the "local umad parameters" below), the libibumad library
+selects the port to use by the following criteria:
+.INDENT 0.0
+.INDENT 3.5
+.INDENT 0.0
+.IP 1. 3
+the first port that is ACTIVE.
+.IP 2. 3
+if not found, the first port that is UP (physical link up).
+.UNINDENT
+.sp
+If a port and/or CA name is specified, the libibumad library attempts
+to fulfill the user request, and will fail if it is not possible.
+.sp
+For example:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+ibaddr # use the first port (criteria #1 above)
+ibaddr \-C mthca1 # pick the best port from "mthca1" only.
+ibaddr \-P 2 # use the second (active/up) port from the first available IB device.
+ibaddr \-C mthca0 \-P 2 # use the specified port only.
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS Debugging flags
+.\" Define the common option -d
+.
+.INDENT 0.0
+.TP
+.B \-d
+raise the IB debugging level.
+May be used several times (\-ddd or \-d \-d \-d).
+.UNINDENT
+.\" Define the common option -e
+.
+.INDENT 0.0
+.TP
+.B \-e
+show send and receive errors (timeouts and others)
+.UNINDENT
+.\" Define the common option -h
+.
+.sp
+\fB\-h, \-\-help\fP show the usage message
+.\" Define the common option -v
+.
+.INDENT 0.0
+.TP
+.B \fB\-v, \-\-verbose\fP
+increase the application verbosity level.
+May be used several times (\-vv or \-v \-v \-v)
+.UNINDENT
+.\" Define the common option -V
+.
+.sp
+\fB\-V, \-\-version\fP show the version info.
+.SS Configuration flags
+.\" Define the common option -t
+.
+.sp
+\fB\-t, \-\-timeout <timeout_ms>\fP override the default timeout for the solicited mads.
+.\" Define the common option -z
+.
+.INDENT 0.0
+.TP
+.B \fB\-\-outstanding_smps, \-o <val>\fP
+Specify the number of outstanding SMP\(aqs which should be issued during the scan
+.sp
+Default: 2
+.UNINDENT
+.\" Define the common option --node-name-map
+.
+.sp
+\fB\-\-node\-name\-map <node\-name\-map>\fP Specify a node name map.
+.INDENT 0.0
+.INDENT 3.5
+This file maps GUIDs to more user friendly names. See FILES section.
+.UNINDENT
+.UNINDENT
+.\" Define the common option -z
+.
+.sp
+\fB\-\-config, \-z <config_file>\fP Specify alternate config file.
+.INDENT 0.0
+.INDENT 3.5
+Default: /etc/infiniband-diags/ibdiag.conf
+.UNINDENT
+.UNINDENT
+.SS COMMON FILES
+.\" Common text for the config file
+.
+.SS CONFIG FILE
+.sp
+/etc/infiniband-diags/ibdiag.conf
+.sp
+A global config file is provided to set some of the common options for all
+tools. See supplied config file for details.
+.\" Common text to describe the node name map file.
+.
+.SS NODE NAME MAP FILE FORMAT
+.sp
+The node name map is used to specify user friendly names for nodes in the
+output. GUIDs are used to perform the lookup.
+.sp
+This functionality is provided by the opensm\-libs package. See \fBopensm(8)\fP
+for the file location for your installation.
+.sp
+\fBGenerically:\fP
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+# comment
+<guid> "<name>"
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+\fBExample:\fP
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+# IB1
+# Line cards
+0x0008f104003f125c "IB1 (Rack 11 slot 1 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f125d "IB1 (Rack 11 slot 1 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f10d2 "IB1 (Rack 11 slot 2 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f10d3 "IB1 (Rack 11 slot 2 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f10bf "IB1 (Rack 11 slot 12 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+
+# Spines
+0x0008f10400400e2d "IB1 (Rack 11 spine 1 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e2e "IB1 (Rack 11 spine 1 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e2f "IB1 (Rack 11 spine 1 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e31 "IB1 (Rack 11 spine 2 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e32 "IB1 (Rack 11 spine 2 ) ISR9288 Voltaire sFB\-12D"
+
+# GUID Node Name
+0x0008f10400411a08 "SW1 (Rack 3) ISR9024 Voltaire 9024D"
+0x0008f10400411a28 "SW2 (Rack 3) ISR9024 Voltaire 9024D"
+0x0008f10400411a34 "SW3 (Rack 3) ISR9024 Voltaire 9024D"
+0x0008f104004119d0 "SW4 (Rack 3) ISR9024 Voltaire 9024D"
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SS DEPENDENCIES
+.sp
+OpenSM (or other running SM/SA), libosmcomp, libibumad, libibmad
+.SS AUTHORS
+.INDENT 0.0
+.TP
+.B Ira Weiny
+< \fI\%ira.weiny@intel.com\fP >
+.TP
+.B Hal Rosenstock
+< \fI\%halr@mellanox.com\fP >
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/contrib/ofed/infiniband-diags/man/sminfo.8 b/contrib/ofed/infiniband-diags/man/sminfo.8
new file mode 100644
index 000000000000..1ab235ef8785
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/man/sminfo.8
@@ -0,0 +1,215 @@
+.\" Man page generated from reStructuredText.
+.
+.TH SMINFO 8 "" "" "Open IB Diagnostics"
+.SH NAME
+SMINFO \-
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.SH QUERY INFINIBAND SMINFO ATTRIBUTE
+.SS SYNOPSIS
+.sp
+sminfo [options] sm_lid | sm_dr_path [modifier]
+.SS DESCRIPTION
+.sp
+Optionally set and display the output of a sminfo query in human readable
+format. The target SM is the one listed in the local port info, or the SM
+specified by the optional SM lid or by the SM direct routed path.
+.sp
+Note: using sminfo for any purposes other then simple query may be very
+dangerous, and may result in a malfunction of the target SM.
+.SS OPTIONS
+.INDENT 0.0
+.TP
+.B \fB\-s, \-\-state <state>\fP set SM state
+0 not active
+.sp
+1 discovering
+.sp
+2 standby
+.sp
+3 master
+.UNINDENT
+.sp
+\fB\-p, \-\-priority <priority>\fP set priority (0\-15)
+.sp
+\fB\-a, \-\-activity <val>\fP set activity count
+.SS Addressing Flags
+.\" Define the common option -D for Directed routes
+.
+.sp
+\fB\-D, \-\-Direct\fP The address specified is a directed route
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+Examples:
+ [options] \-D [options] "0" # self port
+ [options] \-D [options] "0,1,2,1,4" # out via port 1, then 2, ...
+
+ (Note the second number in the path specified must match the port being
+ used. This can be specified using the port selection flag \(aq\-P\(aq or the
+ port found through the automatic selection process.)
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.\" Define the common option -G
+.
+.sp
+\fB\-G, \-\-Guid\fP The address specified is a Port GUID
+.\" Define the common option -L
+.
+.sp
+\fB\-L, \-\-Lid\fP The address specified is a LID
+.SS Port Selection flags
+.\" Define the common option -C
+.
+.sp
+\fB\-C, \-\-Ca <ca_name>\fP use the specified ca_name.
+.\" Define the common option -P
+.
+.sp
+\fB\-P, \-\-Port <ca_port>\fP use the specified ca_port.
+.\" Explanation of local port selection
+.
+.SS Local port Selection
+.sp
+Multiple port/Multiple CA support: when no IB device or port is specified
+(see the "local umad parameters" below), the libibumad library
+selects the port to use by the following criteria:
+.INDENT 0.0
+.INDENT 3.5
+.INDENT 0.0
+.IP 1. 3
+the first port that is ACTIVE.
+.IP 2. 3
+if not found, the first port that is UP (physical link up).
+.UNINDENT
+.sp
+If a port and/or CA name is specified, the libibumad library attempts
+to fulfill the user request, and will fail if it is not possible.
+.sp
+For example:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+ibaddr # use the first port (criteria #1 above)
+ibaddr \-C mthca1 # pick the best port from "mthca1" only.
+ibaddr \-P 2 # use the second (active/up) port from the first available IB device.
+ibaddr \-C mthca0 \-P 2 # use the specified port only.
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS Debugging flags
+.\" Define the common option -d
+.
+.INDENT 0.0
+.TP
+.B \-d
+raise the IB debugging level.
+May be used several times (\-ddd or \-d \-d \-d).
+.UNINDENT
+.\" Define the common option -e
+.
+.INDENT 0.0
+.TP
+.B \-e
+show send and receive errors (timeouts and others)
+.UNINDENT
+.\" Define the common option -h
+.
+.sp
+\fB\-h, \-\-help\fP show the usage message
+.\" Define the common option -v
+.
+.INDENT 0.0
+.TP
+.B \fB\-v, \-\-verbose\fP
+increase the application verbosity level.
+May be used several times (\-vv or \-v \-v \-v)
+.UNINDENT
+.\" Define the common option -V
+.
+.sp
+\fB\-V, \-\-version\fP show the version info.
+.SS Configuration flags
+.\" Define the common option -t
+.
+.sp
+\fB\-t, \-\-timeout <timeout_ms>\fP override the default timeout for the solicited mads.
+.\" Define the common option -y
+.
+.INDENT 0.0
+.TP
+.B \fB\-y, \-\-m_key <key>\fP
+use the specified M_key for requests. If non\-numeric value (like \(aqx\(aq)
+is specified then a value will be prompted for.
+.UNINDENT
+.\" Define the common option -z
+.
+.sp
+\fB\-\-config, \-z <config_file>\fP Specify alternate config file.
+.INDENT 0.0
+.INDENT 3.5
+Default: /etc/infiniband-diags/ibdiag.conf
+.UNINDENT
+.UNINDENT
+.SS FILES
+.\" Common text for the config file
+.
+.SS CONFIG FILE
+.sp
+/etc/infiniband-diags/ibdiag.conf
+.sp
+A global config file is provided to set some of the common options for all
+tools. See supplied config file for details.
+.SS EXAMPLES
+.INDENT 0.0
+.TP
+.B ::
+sminfo # local port\(aqs sminfo
+sminfo 32 # show sminfo of lid 32
+sminfo \-G 0x8f1040023 # same but using guid address
+.UNINDENT
+.SS SEE ALSO
+.sp
+smpdump (8)
+.SS AUTHOR
+.INDENT 0.0
+.TP
+.B Hal Rosenstock
+< \fI\%halr@voltaire.com\fP >
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/contrib/ofed/infiniband-diags/man/smpdump.8 b/contrib/ofed/infiniband-diags/man/smpdump.8
new file mode 100644
index 000000000000..8225f6356592
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/man/smpdump.8
@@ -0,0 +1,207 @@
+.\" Man page generated from reStructuredText.
+.
+.TH SMPDUMP 8 "" "" "Open IB Diagnostics"
+.SH NAME
+SMPDUMP \-
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.SH DUMP INFINIBAND SUBNET MANAGEMENT ATTRIBUTES
+.SS SYNOPSIS
+.sp
+smpdump [options] <dlid|dr_path> <attribute> [attribute_modifier]
+.SS DESCRIPTION
+.sp
+smpdump is a general purpose SMP utility which gets SM attributes from a
+specified SMA. The result is dumped in hex by default.
+.SS OPTIONS
+.INDENT 0.0
+.TP
+.B \fBdlid|drpath\fP
+LID or DR path to SMA
+.TP
+.B \fBattribute\fP
+IBA attribute ID for SM attribute
+.TP
+.B \fBattribute_modifier\fP
+IBA modifier for SM attribute
+.TP
+.B \fB\-s, \-\-string\fP
+Print strings in packet if possible
+.UNINDENT
+.SS Addressing Flags
+.\" Define the common option -D for Directed routes
+.
+.sp
+\fB\-D, \-\-Direct\fP The address specified is a directed route
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+Examples:
+ [options] \-D [options] "0" # self port
+ [options] \-D [options] "0,1,2,1,4" # out via port 1, then 2, ...
+
+ (Note the second number in the path specified must match the port being
+ used. This can be specified using the port selection flag \(aq\-P\(aq or the
+ port found through the automatic selection process.)
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.\" Define the common option -L
+.
+.sp
+\fB\-L, \-\-Lid\fP The address specified is a LID
+.SS Port Selection flags
+.\" Define the common option -C
+.
+.sp
+\fB\-C, \-\-Ca <ca_name>\fP use the specified ca_name.
+.\" Define the common option -P
+.
+.sp
+\fB\-P, \-\-Port <ca_port>\fP use the specified ca_port.
+.\" Explanation of local port selection
+.
+.SS Local port Selection
+.sp
+Multiple port/Multiple CA support: when no IB device or port is specified
+(see the "local umad parameters" below), the libibumad library
+selects the port to use by the following criteria:
+.INDENT 0.0
+.INDENT 3.5
+.INDENT 0.0
+.IP 1. 3
+the first port that is ACTIVE.
+.IP 2. 3
+if not found, the first port that is UP (physical link up).
+.UNINDENT
+.sp
+If a port and/or CA name is specified, the libibumad library attempts
+to fulfill the user request, and will fail if it is not possible.
+.sp
+For example:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+ibaddr # use the first port (criteria #1 above)
+ibaddr \-C mthca1 # pick the best port from "mthca1" only.
+ibaddr \-P 2 # use the second (active/up) port from the first available IB device.
+ibaddr \-C mthca0 \-P 2 # use the specified port only.
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS Debugging flags
+.\" Define the common option -d
+.
+.INDENT 0.0
+.TP
+.B \-d
+raise the IB debugging level.
+May be used several times (\-ddd or \-d \-d \-d).
+.UNINDENT
+.\" Define the common option -e
+.
+.INDENT 0.0
+.TP
+.B \-e
+show send and receive errors (timeouts and others)
+.UNINDENT
+.\" Define the common option -h
+.
+.sp
+\fB\-h, \-\-help\fP show the usage message
+.\" Define the common option -v
+.
+.INDENT 0.0
+.TP
+.B \fB\-v, \-\-verbose\fP
+increase the application verbosity level.
+May be used several times (\-vv or \-v \-v \-v)
+.UNINDENT
+.\" Define the common option -V
+.
+.sp
+\fB\-V, \-\-version\fP show the version info.
+.SS Configuration flags
+.\" Define the common option -t
+.
+.sp
+\fB\-t, \-\-timeout <timeout_ms>\fP override the default timeout for the solicited mads.
+.\" Define the common option -z
+.
+.sp
+\fB\-\-config, \-z <config_file>\fP Specify alternate config file.
+.INDENT 0.0
+.INDENT 3.5
+Default: /etc/infiniband-diags/ibdiag.conf
+.UNINDENT
+.UNINDENT
+.SS FILES
+.\" Common text for the config file
+.
+.SS CONFIG FILE
+.sp
+/etc/infiniband-diags/ibdiag.conf
+.sp
+A global config file is provided to set some of the common options for all
+tools. See supplied config file for details.
+.SS EXAMPLES
+.sp
+Direct Routed Examples
+.INDENT 0.0
+.TP
+.B ::
+smpdump \-D 0,1,2,3,5 16 # NODE DESC
+smpdump \-D 0,1,2 0x15 2 # PORT INFO, port 2
+.UNINDENT
+.sp
+LID Routed Examples
+.INDENT 0.0
+.TP
+.B ::
+smpdump 3 0x15 2 # PORT INFO, lid 3 port 2
+smpdump 0xa0 0x11 # NODE INFO, lid 0xa0
+.UNINDENT
+.SS SEE ALSO
+.sp
+smpquery (8)
+.SS AUTHOR
+.INDENT 0.0
+.TP
+.B Hal Rosenstock
+< \fI\%halr@voltaire.com\fP >
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/contrib/ofed/infiniband-diags/man/smpquery.8 b/contrib/ofed/infiniband-diags/man/smpquery.8
new file mode 100644
index 000000000000..c4dd24fa2555
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/man/smpquery.8
@@ -0,0 +1,310 @@
+.\" Man page generated from reStructuredText.
+.
+.TH SMPQUERY 8 "" "" "Open IB Diagnostics"
+.SH NAME
+SMPQUERY \-
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.SH QUERY INFINIBAND SUBNET MANAGEMENT ATTRIBUTES
+.SS SYNOPSIS
+.sp
+smpquery [options] <op> <dest dr_path|lid|guid> [op params]
+.SS DESCRIPTION
+.sp
+smpquery allows a basic subset of standard SMP queries including the following:
+node info, node description, switch info, port info. Fields are displayed in
+human readable format.
+.SS OPTIONS
+.sp
+Current supported operations (case insensitive) and their parameters:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+Nodeinfo (NI) <addr>
+
+Nodedesc (ND) <addr>
+
+Portinfo (PI) <addr> [<portnum>] # default port is zero
+
+PortInfoExtended (PIE) <addr> [<portnum>]
+
+Switchinfo (SI) <addr>
+
+PKeyTable (PKeys) <addr> [<portnum>]
+
+SL2VLTable (SL2VL) <addr> [<portnum>]
+
+VLArbitration (VLArb) <addr> [<portnum>]
+
+GUIDInfo (GI) <addr>
+
+MlnxExtPortInfo (MEPI) <addr> [<portnum>] # default port is zero
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.INDENT 0.0
+.TP
+.B \fB\-c, \-\-combined\fP
+Use Combined route address argument \fB<lid> <DR_Path>\fP
+.TP
+.B \fB\-x, \-\-extended\fP
+Set SMSupportsExtendedSpeeds bit 31 in AttributeModifier
+(only impacts PortInfo queries).
+.UNINDENT
+.\" Define the common option -K
+.
+.INDENT 0.0
+.TP
+.B \fB\-K, \-\-show_keys\fP
+show security keys (mkey, smkey, etc.) associated with the request.
+.UNINDENT
+.SS Addressing Flags
+.\" Define the common option -D for Directed routes
+.
+.sp
+\fB\-D, \-\-Direct\fP The address specified is a directed route
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+Examples:
+ [options] \-D [options] "0" # self port
+ [options] \-D [options] "0,1,2,1,4" # out via port 1, then 2, ...
+
+ (Note the second number in the path specified must match the port being
+ used. This can be specified using the port selection flag \(aq\-P\(aq or the
+ port found through the automatic selection process.)
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.\" Define the common option -G
+.
+.sp
+\fB\-G, \-\-Guid\fP The address specified is a Port GUID
+.\" Define the common option -L
+.
+.sp
+\fB\-L, \-\-Lid\fP The address specified is a LID
+.\" Define the common option -s
+.
+.sp
+\fB\-s, \-\-sm_port <smlid>\fP use \(aqsmlid\(aq as the target lid for SA queries.
+.SS Port Selection flags
+.\" Define the common option -C
+.
+.sp
+\fB\-C, \-\-Ca <ca_name>\fP use the specified ca_name.
+.\" Define the common option -P
+.
+.sp
+\fB\-P, \-\-Port <ca_port>\fP use the specified ca_port.
+.\" Explanation of local port selection
+.
+.SS Local port Selection
+.sp
+Multiple port/Multiple CA support: when no IB device or port is specified
+(see the "local umad parameters" below), the libibumad library
+selects the port to use by the following criteria:
+.INDENT 0.0
+.INDENT 3.5
+.INDENT 0.0
+.IP 1. 3
+the first port that is ACTIVE.
+.IP 2. 3
+if not found, the first port that is UP (physical link up).
+.UNINDENT
+.sp
+If a port and/or CA name is specified, the libibumad library attempts
+to fulfill the user request, and will fail if it is not possible.
+.sp
+For example:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+ibaddr # use the first port (criteria #1 above)
+ibaddr \-C mthca1 # pick the best port from "mthca1" only.
+ibaddr \-P 2 # use the second (active/up) port from the first available IB device.
+ibaddr \-C mthca0 \-P 2 # use the specified port only.
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS Debugging flags
+.\" Define the common option -d
+.
+.INDENT 0.0
+.TP
+.B \-d
+raise the IB debugging level.
+May be used several times (\-ddd or \-d \-d \-d).
+.UNINDENT
+.\" Define the common option -e
+.
+.INDENT 0.0
+.TP
+.B \-e
+show send and receive errors (timeouts and others)
+.UNINDENT
+.\" Define the common option -h
+.
+.sp
+\fB\-h, \-\-help\fP show the usage message
+.\" Define the common option -v
+.
+.INDENT 0.0
+.TP
+.B \fB\-v, \-\-verbose\fP
+increase the application verbosity level.
+May be used several times (\-vv or \-v \-v \-v)
+.UNINDENT
+.\" Define the common option -V
+.
+.sp
+\fB\-V, \-\-version\fP show the version info.
+.SS Configuration flags
+.\" Define the common option -t
+.
+.sp
+\fB\-t, \-\-timeout <timeout_ms>\fP override the default timeout for the solicited mads.
+.\" Define the common option --node-name-map
+.
+.sp
+\fB\-\-node\-name\-map <node\-name\-map>\fP Specify a node name map.
+.INDENT 0.0
+.INDENT 3.5
+This file maps GUIDs to more user friendly names. See FILES section.
+.UNINDENT
+.UNINDENT
+.\" Define the common option -y
+.
+.INDENT 0.0
+.TP
+.B \fB\-y, \-\-m_key <key>\fP
+use the specified M_key for requests. If non\-numeric value (like \(aqx\(aq)
+is specified then a value will be prompted for.
+.UNINDENT
+.\" Define the common option -z
+.
+.sp
+\fB\-\-config, \-z <config_file>\fP Specify alternate config file.
+.INDENT 0.0
+.INDENT 3.5
+Default: /etc/infiniband-diags/ibdiag.conf
+.UNINDENT
+.UNINDENT
+.SS FILES
+.\" Common text for the config file
+.
+.SS CONFIG FILE
+.sp
+/etc/infiniband-diags/ibdiag.conf
+.sp
+A global config file is provided to set some of the common options for all
+tools. See supplied config file for details.
+.\" Common text to describe the node name map file.
+.
+.SS NODE NAME MAP FILE FORMAT
+.sp
+The node name map is used to specify user friendly names for nodes in the
+output. GUIDs are used to perform the lookup.
+.sp
+This functionality is provided by the opensm\-libs package. See \fBopensm(8)\fP
+for the file location for your installation.
+.sp
+\fBGenerically:\fP
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+# comment
+<guid> "<name>"
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.sp
+\fBExample:\fP
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+# IB1
+# Line cards
+0x0008f104003f125c "IB1 (Rack 11 slot 1 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f125d "IB1 (Rack 11 slot 1 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f10d2 "IB1 (Rack 11 slot 2 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f10d3 "IB1 (Rack 11 slot 2 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+0x0008f104003f10bf "IB1 (Rack 11 slot 12 ) ISR9288/ISR9096 Voltaire sLB\-24D"
+
+# Spines
+0x0008f10400400e2d "IB1 (Rack 11 spine 1 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e2e "IB1 (Rack 11 spine 1 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e2f "IB1 (Rack 11 spine 1 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e31 "IB1 (Rack 11 spine 2 ) ISR9288 Voltaire sFB\-12D"
+0x0008f10400400e32 "IB1 (Rack 11 spine 2 ) ISR9288 Voltaire sFB\-12D"
+
+# GUID Node Name
+0x0008f10400411a08 "SW1 (Rack 3) ISR9024 Voltaire 9024D"
+0x0008f10400411a28 "SW2 (Rack 3) ISR9024 Voltaire 9024D"
+0x0008f10400411a34 "SW3 (Rack 3) ISR9024 Voltaire 9024D"
+0x0008f104004119d0 "SW4 (Rack 3) ISR9024 Voltaire 9024D"
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.SS EXAMPLES
+.INDENT 0.0
+.TP
+.B ::
+smpquery portinfo 3 1 # portinfo by lid, with port modifier
+smpquery \-G switchinfo 0x2C9000100D051 1 # switchinfo by guid
+smpquery \-D nodeinfo 0 # nodeinfo by direct route
+smpquery \-c nodeinfo 6 0,12 # nodeinfo by combined route
+.UNINDENT
+.SS SEE ALSO
+.sp
+smpdump (8)
+.SS AUTHOR
+.INDENT 0.0
+.TP
+.B Hal Rosenstock
+< \fI\%hal@mellanox.com\fP >
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/contrib/ofed/infiniband-diags/man/vendstat.8 b/contrib/ofed/infiniband-diags/man/vendstat.8
new file mode 100644
index 000000000000..a9ede4d0eddd
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/man/vendstat.8
@@ -0,0 +1,221 @@
+.\" Man page generated from reStructuredText.
+.
+.TH VENDSTAT 8 "" "" "Open IB Diagnostics"
+.SH NAME
+VENDSTAT \-
+.
+.nr rst2man-indent-level 0
+.
+.de1 rstReportMargin
+\\$1 \\n[an-margin]
+level \\n[rst2man-indent-level]
+level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
+-
+\\n[rst2man-indent0]
+\\n[rst2man-indent1]
+\\n[rst2man-indent2]
+..
+.de1 INDENT
+.\" .rstReportMargin pre:
+. RS \\$1
+. nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin]
+. nr rst2man-indent-level +1
+.\" .rstReportMargin post:
+..
+.de UNINDENT
+. RE
+.\" indent \\n[an-margin]
+.\" old: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.nr rst2man-indent-level -1
+.\" new: \\n[rst2man-indent\\n[rst2man-indent-level]]
+.in \\n[rst2man-indent\\n[rst2man-indent-level]]u
+..
+.SH QUERY INFINIBAND VENDOR SPECIFIC FUNCTIONS
+.SS SYNOPSIS
+.sp
+vendstat [options] <lid|guid>
+.SS DESCRIPTION
+.sp
+vendstat uses vendor specific MADs to access beyond the IB spec
+vendor specific functionality. Currently, there is support for
+Mellanox InfiniSwitch\-III (IS3) and InfiniSwitch\-IV (IS4).
+.SS OPTIONS
+.INDENT 0.0
+.TP
+.B \fB\-N\fP
+show IS3 or IS4 general information.
+.TP
+.B \fB\-w\fP
+show IS3 port xmit wait counters.
+.TP
+.B \fB\-i\fP
+show IS4 counter group info.
+.TP
+.B \fB\-c <num,num>\fP
+configure IS4 counter groups.
+.sp
+Configure IS4 counter groups 0 and 1. Such configuration is not
+persistent across IS4 reboot. First number is for counter group 0 and
+second is for counter group 1.
+.sp
+Group 0 counter config values:
+.UNINDENT
+.INDENT 0.0
+.TP
+.B ::
+.INDENT 7.0
+.INDENT 3.5
+0 \- PortXmitDataSL0\-7
+1 \- PortXmitDataSL8\-15
+2 \- PortRcvDataSL0\-7
+.UNINDENT
+.UNINDENT
+.sp
+Group 1 counter config values:
+.UNINDENT
+.INDENT 0.0
+.TP
+.B ::
+1 \- PortXmitDataSL8\-15
+2 \- PortRcvDataSL0\-7
+8 \- PortRcvDataSL8\-15
+.TP
+.B \fB\-R, \-\-Read <addr,mask>\fP
+Read configuration space record at addr
+.TP
+.B \fB\-W, \-\-Write <addr,val,mask>\fP
+Write configuration space record at addr
+.TP
+.B \fB\-\-dgid <gid>\fP
+destination GID: use when GRH is required in packets (IPv6 format)
+.UNINDENT
+.SS Addressing Flags
+.\" Define the common option -G
+.
+.sp
+\fB\-G, \-\-Guid\fP The address specified is a Port GUID
+.\" Define the common option -L
+.
+.sp
+\fB\-L, \-\-Lid\fP The address specified is a LID
+.\" Define the common option -s
+.
+.sp
+\fB\-s, \-\-sm_port <smlid>\fP use \(aqsmlid\(aq as the target lid for SA queries.
+.SS Port Selection flags
+.\" Define the common option -C
+.
+.sp
+\fB\-C, \-\-Ca <ca_name>\fP use the specified ca_name.
+.\" Define the common option -P
+.
+.sp
+\fB\-P, \-\-Port <ca_port>\fP use the specified ca_port.
+.\" Explanation of local port selection
+.
+.SS Local port Selection
+.sp
+Multiple port/Multiple CA support: when no IB device or port is specified
+(see the "local umad parameters" below), the libibumad library
+selects the port to use by the following criteria:
+.INDENT 0.0
+.INDENT 3.5
+.INDENT 0.0
+.IP 1. 3
+the first port that is ACTIVE.
+.IP 2. 3
+if not found, the first port that is UP (physical link up).
+.UNINDENT
+.sp
+If a port and/or CA name is specified, the libibumad library attempts
+to fulfill the user request, and will fail if it is not possible.
+.sp
+For example:
+.INDENT 0.0
+.INDENT 3.5
+.sp
+.nf
+.ft C
+ibaddr # use the first port (criteria #1 above)
+ibaddr \-C mthca1 # pick the best port from "mthca1" only.
+ibaddr \-P 2 # use the second (active/up) port from the first available IB device.
+ibaddr \-C mthca0 \-P 2 # use the specified port only.
+.ft P
+.fi
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.UNINDENT
+.SS Debugging flags
+.\" Define the common option -d
+.
+.INDENT 0.0
+.TP
+.B \-d
+raise the IB debugging level.
+May be used several times (\-ddd or \-d \-d \-d).
+.UNINDENT
+.\" Define the common option -e
+.
+.INDENT 0.0
+.TP
+.B \-e
+show send and receive errors (timeouts and others)
+.UNINDENT
+.\" Define the common option -h
+.
+.sp
+\fB\-h, \-\-help\fP show the usage message
+.\" Define the common option -v
+.
+.INDENT 0.0
+.TP
+.B \fB\-v, \-\-verbose\fP
+increase the application verbosity level.
+May be used several times (\-vv or \-v \-v \-v)
+.UNINDENT
+.\" Define the common option -V
+.
+.sp
+\fB\-V, \-\-version\fP show the version info.
+.SS Configuration flags
+.\" Define the common option -t
+.
+.sp
+\fB\-t, \-\-timeout <timeout_ms>\fP override the default timeout for the solicited mads.
+.\" Define the common option -z
+.
+.sp
+\fB\-\-config, \-z <config_file>\fP Specify alternate config file.
+.INDENT 0.0
+.INDENT 3.5
+Default: /etc/infiniband-diags/ibdiag.conf
+.UNINDENT
+.UNINDENT
+.SS FILES
+.\" Common text for the config file
+.
+.SS CONFIG FILE
+.sp
+/etc/infiniband-diags/ibdiag.conf
+.sp
+A global config file is provided to set some of the common options for all
+tools. See supplied config file for details.
+.SS EXAMPLES
+.INDENT 0.0
+.TP
+.B ::
+vendstat \-N 6 # read IS3 or IS4 general information
+vendstat \-w 6 # read IS3 port xmit wait counters
+vendstat \-i 6 12 # read IS4 port 12 counter group info
+vendstat \-c 0,1 6 12 # configure IS4 port 12 counter groups for PortXmitDataSL
+vendstat \-c 2,8 6 12 # configure IS4 port 12 counter groups for PortRcvDataSL
+.UNINDENT
+.SS AUTHOR
+.INDENT 0.0
+.TP
+.B Hal Rosenstock
+< \fI\%hal.rosenstock@gmail.com\fP >
+.UNINDENT
+.\" Generated by docutils manpage writer.
+.
diff --git a/contrib/ofed/infiniband-diags/src/dump_fts.c b/contrib/ofed/infiniband-diags/src/dump_fts.c
new file mode 100644
index 000000000000..387211f9024e
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/src/dump_fts.c
@@ -0,0 +1,497 @@
+/*
+ * Copyright (c) 2004-2009 Voltaire Inc. All rights reserved.
+ * Copyright (c) 2009-2011 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 2013 Lawrence Livermore National Security. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <inttypes.h>
+#include <getopt.h>
+#include <netinet/in.h>
+#include <assert.h>
+
+#include <infiniband/umad.h>
+#include <infiniband/mad.h>
+#include <complib/cl_nodenamemap.h>
+
+#include <infiniband/ibnetdisc.h>
+
+#include "ibdiag_common.h"
+
+struct ibmad_port *srcport;
+
+unsigned startlid = 0, endlid = 0;
+
+static int brief, dump_all, multicast;
+
+static char *node_name_map_file = NULL;
+static nn_map_t *node_name_map = NULL;
+
+#define IB_MLIDS_IN_BLOCK (IB_SMP_DATA_SIZE/2)
+
+int dump_mlid(char *str, int strlen, unsigned mlid, unsigned nports,
+ uint16_t mft[16][IB_MLIDS_IN_BLOCK])
+{
+ uint16_t mask;
+ unsigned i, chunk, bit, nonzero = 0;
+
+ if (brief) {
+ int n = 0;
+ unsigned chunks = ALIGN(nports + 1, 16) / 16;
+ for (i = 0; i < chunks; i++) {
+ mask = ntohs(mft[i][mlid % IB_MLIDS_IN_BLOCK]);
+ if (mask)
+ nonzero++;
+ n += snprintf(str + n, strlen - n, "%04hx", mask);
+ if (n >= strlen) {
+ n = strlen;
+ break;
+ }
+ }
+ if (!nonzero && !dump_all) {
+ str[0] = 0;
+ return 0;
+ }
+ return n;
+ }
+ for (i = 0; i <= nports; i++) {
+ chunk = i / 16;
+ bit = i % 16;
+
+ mask = ntohs(mft[chunk][mlid % IB_MLIDS_IN_BLOCK]);
+ if (mask)
+ nonzero++;
+ str[i * 2] = (mask & (1 << bit)) ? 'x' : ' ';
+ str[i * 2 + 1] = ' ';
+ }
+ if (!nonzero && !dump_all) {
+ str[0] = 0;
+ return 0;
+ }
+ str[i * 2] = 0;
+ return i * 2;
+}
+
+uint16_t mft[16][IB_MLIDS_IN_BLOCK] = { { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0}, { 0 }, { 0 } };
+
+void dump_multicast_tables(ibnd_node_t * node, unsigned startlid,
+ unsigned endlid, struct ibmad_port * mad_port)
+{
+ ib_portid_t *portid = &node->path_portid;
+ char nd[IB_SMP_DATA_SIZE] = { 0 };
+ char str[512];
+ char *s;
+ uint64_t nodeguid;
+ uint32_t mod;
+ unsigned block, i, j, e, nports, cap, chunks, startblock, lastblock,
+ top;
+ char *mapnd = NULL;
+ int n = 0;
+
+ memcpy(nd, node->nodedesc, strlen(node->nodedesc));
+ nports = node->numports;
+ nodeguid = node->guid;
+
+ mad_decode_field(node->switchinfo, IB_SW_MCAST_FDB_CAP_F, &cap);
+ mad_decode_field(node->switchinfo, IB_SW_MCAST_FDB_TOP_F, &top);
+
+ if (!endlid || endlid > IB_MIN_MCAST_LID + cap - 1)
+ endlid = IB_MIN_MCAST_LID + cap - 1;
+ if (!dump_all && top && top < endlid) {
+ if (top < IB_MIN_MCAST_LID - 1)
+ IBWARN("illegal top mlid %x", top);
+ else
+ endlid = top;
+ }
+
+ if (!startlid)
+ startlid = IB_MIN_MCAST_LID;
+ else if (startlid < IB_MIN_MCAST_LID) {
+ IBWARN("illegal start mlid %x, set to %x", startlid,
+ IB_MIN_MCAST_LID);
+ startlid = IB_MIN_MCAST_LID;
+ }
+
+ if (endlid > IB_MAX_MCAST_LID) {
+ IBWARN("illegal end mlid %x, truncate to %x", endlid,
+ IB_MAX_MCAST_LID);
+ endlid = IB_MAX_MCAST_LID;
+ }
+
+ mapnd = remap_node_name(node_name_map, nodeguid, nd);
+
+ printf("Multicast mlids [0x%x-0x%x] of switch %s guid 0x%016" PRIx64
+ " (%s):\n", startlid, endlid, portid2str(portid), nodeguid,
+ mapnd);
+
+ if (brief)
+ printf(" MLid Port Mask\n");
+ else {
+ if (nports > 9) {
+ for (i = 0, s = str; i <= nports; i++) {
+ *s++ = (i % 10) ? ' ' : '0' + i / 10;
+ *s++ = ' ';
+ }
+ *s = 0;
+ printf(" %s\n", str);
+ }
+ for (i = 0, s = str; i <= nports; i++)
+ s += sprintf(s, "%d ", i % 10);
+ printf(" Ports: %s\n", str);
+ printf(" MLid\n");
+ }
+ if (ibverbose)
+ printf("Switch multicast mlid capability is %d top is 0x%x\n",
+ cap, top);
+
+ chunks = ALIGN(nports + 1, 16) / 16;
+
+ startblock = startlid / IB_MLIDS_IN_BLOCK;
+ lastblock = endlid / IB_MLIDS_IN_BLOCK;
+ for (block = startblock; block <= lastblock; block++) {
+ for (j = 0; j < chunks; j++) {
+ int status;
+ mod = (block - IB_MIN_MCAST_LID / IB_MLIDS_IN_BLOCK)
+ | (j << 28);
+
+ DEBUG("reading block %x chunk %d mod %x", block, j,
+ mod);
+ if (!smp_query_status_via
+ (mft + j, portid, IB_ATTR_MULTICASTFORWTBL, mod, 0,
+ &status, mad_port)) {
+ fprintf(stderr, "SubnGet(MFT) failed on switch "
+ "'%s' %s Node GUID 0x%"PRIx64
+ " SMA LID %d; MAD status 0x%x "
+ "AM 0x%x\n",
+ mapnd, portid2str(portid),
+ node->guid, node->smalid,
+ status, mod);
+ }
+ }
+
+ i = block * IB_MLIDS_IN_BLOCK;
+ e = i + IB_MLIDS_IN_BLOCK;
+ if (i < startlid)
+ i = startlid;
+ if (e > endlid + 1)
+ e = endlid + 1;
+
+ for (; i < e; i++) {
+ if (dump_mlid(str, sizeof str, i, nports, mft) == 0)
+ continue;
+ printf("0x%04x %s\n", i, str);
+ n++;
+ }
+ }
+
+ printf("%d %smlids dumped \n", n, dump_all ? "" : "valid ");
+
+ free(mapnd);
+}
+
+int dump_lid(char *str, int str_len, int lid, int valid,
+ ibnd_fabric_t *fabric,
+ int * last_port_lid, int * base_port_lid,
+ uint64_t * portguid)
+{
+ char nd[IB_SMP_DATA_SIZE] = { 0 };
+
+ ibnd_port_t *port = NULL;
+
+ char ntype[50], sguid[30];
+ uint64_t nodeguid;
+ int baselid, lmc, type;
+ char *mapnd = NULL;
+ int rc;
+
+ if (brief) {
+ str[0] = 0;
+ return 0;
+ }
+
+ if (lid <= *last_port_lid) {
+ if (!valid)
+ return snprintf(str, str_len,
+ ": (path #%d - illegal port)",
+ lid - *base_port_lid);
+ else if (!*portguid)
+ return snprintf(str, str_len,
+ ": (path #%d out of %d)",
+ lid - *base_port_lid + 1,
+ *last_port_lid - *base_port_lid + 1);
+ else {
+ return snprintf(str, str_len,
+ ": (path #%d out of %d: portguid %s)",
+ lid - *base_port_lid + 1,
+ *last_port_lid - *base_port_lid + 1,
+ mad_dump_val(IB_NODE_PORT_GUID_F, sguid,
+ sizeof sguid, portguid));
+ }
+ }
+
+ if (!valid)
+ return snprintf(str, str_len, ": (illegal port)");
+
+ *portguid = 0;
+
+ port = ibnd_find_port_lid(fabric, lid);
+ if (!port) {
+ return snprintf(str, str_len, ": (node info not available fabric scan)");
+ }
+
+ nodeguid = port->node->guid;
+ *portguid = port->guid;
+ type = port->node->type;
+
+ baselid = port->base_lid;
+ lmc = port->lmc;
+
+ memcpy(nd, port->node->nodedesc, strlen(port->node->nodedesc));
+
+ if (lmc > 0) {
+ *base_port_lid = baselid;
+ *last_port_lid = baselid + (1 << lmc) - 1;
+ }
+
+ mapnd = remap_node_name(node_name_map, nodeguid, nd);
+
+ rc = snprintf(str, str_len, ": (%s portguid %s: '%s')",
+ mad_dump_val(IB_NODE_TYPE_F, ntype, sizeof ntype,
+ &type), mad_dump_val(IB_NODE_PORT_GUID_F,
+ sguid, sizeof sguid,
+ portguid),
+ mapnd);
+
+ free(mapnd);
+ return rc;
+}
+
+void dump_unicast_tables(ibnd_node_t * node, int startlid, int endlid,
+ struct ibmad_port *mad_port, ibnd_fabric_t *fabric)
+{
+ ib_portid_t * portid = &node->path_portid;
+ char lft[IB_SMP_DATA_SIZE] = { 0 };
+ char nd[IB_SMP_DATA_SIZE] = { 0 };
+ char str[200];
+ uint64_t nodeguid;
+ int block, i, e, top;
+ unsigned nports;
+ int n = 0, startblock, endblock;
+ char *mapnd = NULL;
+ int last_port_lid = 0, base_port_lid = 0;
+ uint64_t portguid = 0;
+
+ mad_decode_field(node->switchinfo, IB_SW_LINEAR_FDB_TOP_F, &top);
+ nodeguid = node->guid;
+ nports = node->numports;
+ memcpy(nd, node->nodedesc, strlen(node->nodedesc));
+
+ if (!endlid || endlid > top)
+ endlid = top;
+
+ if (endlid > IB_MAX_UCAST_LID) {
+ IBWARN("illegal lft top %d, truncate to %d", endlid,
+ IB_MAX_UCAST_LID);
+ endlid = IB_MAX_UCAST_LID;
+ }
+
+ mapnd = remap_node_name(node_name_map, nodeguid, nd);
+
+ printf("Unicast lids [0x%x-0x%x] of switch %s guid 0x%016" PRIx64
+ " (%s):\n", startlid, endlid, portid2str(portid), nodeguid,
+ mapnd);
+
+ DEBUG("Switch top is 0x%x\n", top);
+
+ printf(" Lid Out Destination\n");
+ printf(" Port Info \n");
+ startblock = startlid / IB_SMP_DATA_SIZE;
+ endblock = ALIGN(endlid, IB_SMP_DATA_SIZE) / IB_SMP_DATA_SIZE;
+ for (block = startblock; block < endblock; block++) {
+ int status;
+ DEBUG("reading block %d", block);
+ if (!smp_query_status_via(lft, portid, IB_ATTR_LINEARFORWTBL, block,
+ 0, &status, mad_port)) {
+ fprintf(stderr, "SubnGet(LFT) failed on switch "
+ "'%s' %s Node GUID 0x%"PRIx64
+ " SMA LID %d; MAD status 0x%x AM 0x%x\n",
+ mapnd, portid2str(portid),
+ node->guid, node->smalid,
+ status, block);
+ }
+ i = block * IB_SMP_DATA_SIZE;
+ e = i + IB_SMP_DATA_SIZE;
+ if (i < startlid)
+ i = startlid;
+ if (e > endlid + 1)
+ e = endlid + 1;
+
+ for (; i < e; i++) {
+ unsigned outport = lft[i % IB_SMP_DATA_SIZE];
+ unsigned valid = (outport <= nports);
+
+ if (!valid && !dump_all)
+ continue;
+ dump_lid(str, sizeof str, i, valid, fabric,
+ &last_port_lid, &base_port_lid, &portguid);
+ printf("0x%04x %03u %s\n", i, outport & 0xff, str);
+ n++;
+ }
+ }
+
+ printf("%d %slids dumped \n", n, dump_all ? "" : "valid ");
+ free(mapnd);
+}
+
+void dump_node(ibnd_node_t *node, struct ibmad_port *mad_port,
+ ibnd_fabric_t *fabric)
+{
+ if (multicast)
+ dump_multicast_tables(node, startlid, endlid, mad_port);
+ else
+ dump_unicast_tables(node, startlid, endlid,
+ mad_port, fabric);
+}
+
+void process_switch(ibnd_node_t * node, void *fabric)
+{
+ dump_node(node, srcport, (ibnd_fabric_t *)fabric);
+}
+
+static int process_opt(void *context, int ch, char *optarg)
+{
+ switch (ch) {
+ case 'a':
+ dump_all++;
+ break;
+ case 'M':
+ multicast++;
+ break;
+ case 'n':
+ brief++;
+ break;
+ case 1:
+ node_name_map_file = strdup(optarg);
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ int rc = 0;
+ int mgmt_classes[3] =
+ { IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS };
+
+ struct ibnd_config config = { 0 };
+ ibnd_fabric_t *fabric = NULL;
+
+ const struct ibdiag_opt opts[] = {
+ {"all", 'a', 0, NULL, "show all lids, even invalid entries"},
+ {"no_dests", 'n', 0, NULL,
+ "do not try to resolve destinations"},
+ {"Multicast", 'M', 0, NULL, "show multicast forwarding tables"},
+ {"node-name-map", 1, 1, "<file>", "node name map file"},
+ {0}
+ };
+ char usage_args[] = "[<dest dr_path|lid|guid> [<startlid> [<endlid>]]]";
+ const char *usage_examples[] = {
+ " -- Unicast examples:",
+ "-a\t# same, but dump all lids, even with invalid out ports",
+ "-n\t# simple dump format - no destination resolving",
+ "10\t# dump lids starting from 10",
+ "0x10 0x20\t# dump lid range",
+ " -- Multicast examples:",
+ "-M\t# dump all non empty mlids of switch with lid 4",
+ "-M 0xc010 0xc020\t# same, but with range",
+ "-M -n\t# simple dump format",
+ NULL,
+ };
+
+ ibdiag_process_opts(argc, argv, &config, "KGDLs", opts, process_opt,
+ usage_args, usage_examples);
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc > 0)
+ startlid = strtoul(argv[0], 0, 0);
+ if (argc > 1)
+ endlid = strtoul(argv[1], 0, 0);
+
+ node_name_map = open_node_name_map(node_name_map_file);
+
+ if (ibd_timeout)
+ config.timeout_ms = ibd_timeout;
+
+ config.flags = ibd_ibnetdisc_flags;
+ config.mkey = ibd_mkey;
+
+ if ((fabric = ibnd_discover_fabric(ibd_ca, ibd_ca_port, NULL,
+ &config)) != NULL) {
+
+ srcport = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 3);
+ if (!srcport) {
+ fprintf(stderr,
+ "Failed to open '%s' port '%d'\n", ibd_ca, ibd_ca_port);
+ rc = -1;
+ goto Exit;
+ }
+ smp_mkey_set(srcport, ibd_mkey);
+
+ if (ibd_timeout) {
+ mad_rpc_set_timeout(srcport, ibd_timeout);
+ }
+
+ ibnd_iter_nodes_type(fabric, process_switch, IB_NODE_SWITCH, fabric);
+
+ mad_rpc_close_port(srcport);
+
+ } else {
+ fprintf(stderr, "Failed to discover fabric\n");
+ rc = -1;
+ }
+Exit:
+ ibnd_destroy_fabric(fabric);
+
+ close_node_name_map(node_name_map);
+ exit(rc);
+}
diff --git a/contrib/ofed/infiniband-diags/src/ibaddr.c b/contrib/ofed/infiniband-diags/src/ibaddr.c
new file mode 100644
index 000000000000..1a721d0a003f
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/src/ibaddr.c
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2004-2009 Voltaire Inc. All rights reserved.
+ * Copyright (c) 2011 Mellanox Technologies LTD. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <arpa/inet.h>
+
+#include <infiniband/umad.h>
+#include <infiniband/mad.h>
+
+#include "ibdiag_common.h"
+
+struct ibmad_port *srcport;
+
+static int ib_resolve_addr(ib_portid_t * portid, int portnum, int show_lid,
+ int show_gid)
+{
+ char gid_str[INET6_ADDRSTRLEN];
+ uint8_t portinfo[IB_SMP_DATA_SIZE] = { 0 };
+ uint8_t nodeinfo[IB_SMP_DATA_SIZE] = { 0 };
+ uint64_t guid, prefix;
+ ibmad_gid_t gid;
+ int lmc;
+
+ if (!smp_query_via(nodeinfo, portid, IB_ATTR_NODE_INFO, 0, 0, srcport))
+ return -1;
+
+ if (!smp_query_via(portinfo, portid, IB_ATTR_PORT_INFO, portnum, 0,
+ srcport))
+ return -1;
+
+ mad_decode_field(portinfo, IB_PORT_LID_F, &portid->lid);
+ mad_decode_field(portinfo, IB_PORT_GID_PREFIX_F, &prefix);
+ mad_decode_field(portinfo, IB_PORT_LMC_F, &lmc);
+ mad_decode_field(nodeinfo, IB_NODE_PORT_GUID_F, &guid);
+
+ mad_encode_field(gid, IB_GID_PREFIX_F, &prefix);
+ mad_encode_field(gid, IB_GID_GUID_F, &guid);
+
+ if (show_gid) {
+ printf("GID %s ", inet_ntop(AF_INET6, gid, gid_str,
+ sizeof gid_str));
+ }
+
+ if (show_lid > 0)
+ printf("LID start 0x%x end 0x%x", portid->lid,
+ portid->lid + (1 << lmc) - 1);
+ else if (show_lid < 0)
+ printf("LID start %u end %u", portid->lid,
+ portid->lid + (1 << lmc) - 1);
+ printf("\n");
+ return 0;
+}
+
+static int show_lid, show_gid;
+
+static int process_opt(void *context, int ch, char *optarg)
+{
+ switch (ch) {
+ case 'g':
+ show_gid = 1;
+ break;
+ case 'l':
+ show_lid++;
+ break;
+ case 'L':
+ show_lid = -100;
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ int mgmt_classes[3] =
+ { IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS };
+ ib_portid_t portid = { 0 };
+ int port = 0;
+
+ const struct ibdiag_opt opts[] = {
+ {"gid_show", 'g', 0, NULL, "show gid address only"},
+ {"lid_show", 'l', 0, NULL, "show lid range only"},
+ {"Lid_show", 'L', 0, NULL, "show lid range (in decimal) only"},
+ {0}
+ };
+ char usage_args[] = "[<lid|dr_path|guid>]";
+ const char *usage_examples[] = {
+ "\t\t# local port's address",
+ "32\t\t# show lid range and gid of lid 32",
+ "-G 0x8f1040023\t# same but using guid address",
+ "-l 32\t\t# show lid range only",
+ "-L 32\t\t# show decimal lid range only",
+ "-g 32\t\t# show gid address only",
+ NULL
+ };
+
+ ibdiag_process_opts(argc, argv, NULL, "KL", opts, process_opt,
+ usage_args, usage_examples);
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc > 1)
+ port = strtoul(argv[1], 0, 0);
+
+ if (!show_lid && !show_gid)
+ show_lid = show_gid = 1;
+
+ srcport = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 3);
+ if (!srcport)
+ IBEXIT("Failed to open '%s' port '%d'", ibd_ca, ibd_ca_port);
+
+ smp_mkey_set(srcport, ibd_mkey);
+
+ if (argc) {
+ if (resolve_portid_str(ibd_ca, ibd_ca_port, &portid, argv[0],
+ ibd_dest_type, ibd_sm_id, srcport) < 0)
+ IBEXIT("can't resolve destination port %s", argv[0]);
+ } else {
+ if (resolve_self(ibd_ca, ibd_ca_port, &portid, &port, NULL) < 0)
+ IBEXIT("can't resolve self port %s", argv[0]);
+ }
+
+ if (ib_resolve_addr(&portid, port, show_lid, show_gid) < 0)
+ IBEXIT("can't resolve requested address");
+
+ mad_rpc_close_port(srcport);
+ exit(0);
+}
diff --git a/contrib/ofed/infiniband-diags/src/ibcacheedit.c b/contrib/ofed/infiniband-diags/src/ibcacheedit.c
new file mode 100644
index 000000000000..b5208390b5ae
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/src/ibcacheedit.c
@@ -0,0 +1,356 @@
+/*
+ * Copyright (c) 2010 Lawrence Livermore National Lab. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include <inttypes.h>
+
+#include <infiniband/mad.h>
+#include <infiniband/ibnetdisc.h>
+
+#include "ibdiag_common.h"
+
+uint64_t switchguid_before = 0;
+uint64_t switchguid_after = 0;
+int switchguid_flag = 0;
+
+uint64_t caguid_before = 0;
+uint64_t caguid_after = 0;
+int caguid_flag = 0;
+
+uint64_t sysimgguid_before = 0;
+uint64_t sysimgguid_after = 0;
+int sysimgguid_flag = 0;
+
+uint64_t portguid_nodeguid = 0;
+uint64_t portguid_before = 0;
+uint64_t portguid_after = 0;
+int portguid_flag = 0;
+
+struct guids {
+ uint64_t searchguid;
+ int searchguid_found;
+ uint64_t before;
+ uint64_t after;
+ int found;
+};
+
+static int parse_beforeafter(char *arg, uint64_t *before, uint64_t *after)
+{
+ char *ptr;
+ char *before_str;
+ char *after_str;
+
+ ptr = strchr(optarg, ':');
+ if (!ptr || !(*(ptr + 1))) {
+ fprintf(stderr, "invalid input '%s'\n", arg);
+ return -1;
+ }
+ (*ptr) = '\0';
+ before_str = arg;
+ after_str = ptr + 1;
+
+ (*before) = strtoull(before_str, 0, 0);
+ (*after) = strtoull(after_str, 0, 0);
+ return 0;
+}
+
+static int parse_guidbeforeafter(char *arg,
+ uint64_t *guid,
+ uint64_t *before,
+ uint64_t *after)
+{
+ char *ptr1;
+ char *ptr2;
+ char *guid_str;
+ char *before_str;
+ char *after_str;
+
+ ptr1 = strchr(optarg, ':');
+ if (!ptr1 || !(*(ptr1 + 1))) {
+ fprintf(stderr, "invalid input '%s'\n", arg);
+ return -1;
+ }
+ guid_str = arg;
+ before_str = ptr1 + 1;
+
+ ptr2 = strchr(before_str, ':');
+ if (!ptr2 || !(*(ptr2 + 1))) {
+ fprintf(stderr, "invalid input '%s'\n", arg);
+ return -1;
+ }
+ (*ptr1) = '\0';
+ (*ptr2) = '\0';
+ after_str = ptr2 + 1;
+
+ (*guid) = strtoull(guid_str, 0, 0);
+ (*before) = strtoull(before_str, 0, 0);
+ (*after) = strtoull(after_str, 0, 0);
+ return 0;
+}
+
+static int process_opt(void *context, int ch, char *optarg)
+{
+ switch (ch) {
+ case 1:
+ if (parse_beforeafter(optarg,
+ &switchguid_before,
+ &switchguid_after) < 0)
+ return -1;
+ switchguid_flag++;
+ break;
+ case 2:
+ if (parse_beforeafter(optarg,
+ &caguid_before,
+ &caguid_after) < 0)
+ return -1;
+ caguid_flag++;
+ break;
+ case 3:
+ if (parse_beforeafter(optarg,
+ &sysimgguid_before,
+ &sysimgguid_after) < 0)
+ return -1;
+ sysimgguid_flag++;
+ break;
+ case 4:
+ if (parse_guidbeforeafter(optarg,
+ &portguid_nodeguid,
+ &portguid_before,
+ &portguid_after) < 0)
+ return -1;
+ portguid_flag++;
+ break;
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+static void update_switchportguids(ibnd_node_t *node)
+{
+ ibnd_port_t *port;
+ int p;
+
+ for (p = 0; p <= node->numports; p++) {
+ port = node->ports[p];
+ if (port)
+ port->guid = node->guid;
+ }
+}
+
+static void replace_node_guid(ibnd_node_t *node, void *user_data)
+{
+ struct guids *guids;
+
+ guids = (struct guids *)user_data;
+
+ if (node->guid == guids->before) {
+
+ node->guid = guids->after;
+
+ /* port guids are identical to switch guids on
+ * switches, so update port guids too
+ */
+ if (node->type == IB_NODE_SWITCH)
+ update_switchportguids(node);
+
+ guids->found++;
+ }
+}
+
+static void replace_sysimgguid(ibnd_node_t *node, void *user_data)
+{
+ struct guids *guids;
+ uint64_t sysimgguid;
+
+ guids = (struct guids *)user_data;
+
+ sysimgguid = mad_get_field64(node->info, 0, IB_NODE_SYSTEM_GUID_F);
+ if (sysimgguid == guids->before) {
+ mad_set_field64(node->info, 0, IB_NODE_SYSTEM_GUID_F,
+ guids->after);
+ guids->found++;
+ }
+}
+
+static void replace_portguid(ibnd_node_t *node, void *user_data)
+{
+ struct guids *guids;
+
+ guids = (struct guids *)user_data;
+
+ if (node->guid != guids->searchguid)
+ return;
+
+ guids->searchguid_found++;
+
+ if (node->type == IB_NODE_SWITCH) {
+ /* port guids are identical to switch guids on
+ * switches, so update switch guid too
+ */
+ if (node->guid == guids->before) {
+ node->guid = guids->after;
+ update_switchportguids(node);
+ guids->found++;
+ }
+ }
+ else {
+ ibnd_port_t *port;
+ int p;
+
+ for (p = 1; p <= node->numports; p++) {
+ port = node->ports[p];
+ if (port
+ && port->guid == guids->before) {
+ port->guid = guids->after;
+ guids->found++;
+ break;
+ }
+ }
+ }
+}
+
+int main(int argc, char **argv)
+{
+ ibnd_fabric_t *fabric = NULL;
+ char *orig_cache_file = NULL;
+ char *new_cache_file = NULL;
+ struct guids guids;
+
+ const struct ibdiag_opt opts[] = {
+ {"switchguid", 1, 1, "BEFOREGUID:AFTERGUID",
+ "Specify before and after switchguid to edit"},
+ {"caguid", 2, 1, "BEFOREGUID:AFTERGUID",
+ "Specify before and after caguid to edit"},
+ {"sysimgguid", 3, 1, "BEFOREGUID:AFTERGUID",
+ "Specify before and after sysimgguid to edit"},
+ {"portguid", 4, 1, "NODEGUID:BEFOREGUID:AFTERGUID",
+ "Specify before and after port guid to edit"},
+ {0}
+ };
+ char *usage_args = "<orig.cache> <new.cache>";
+
+ ibdiag_process_opts(argc, argv, NULL, "CDdeGKLPstvy",
+ opts, process_opt, usage_args,
+ NULL);
+
+ argc -= optind;
+ argv += optind;
+
+ orig_cache_file = argv[0];
+ new_cache_file = argv[1];
+
+ if (!orig_cache_file)
+ IBEXIT("original cache file not specified");
+
+ if (!new_cache_file)
+ IBEXIT("new cache file not specified");
+
+ if ((fabric = ibnd_load_fabric(orig_cache_file, 0)) == NULL)
+ IBEXIT("loading original cached fabric failed");
+
+ if (switchguid_flag) {
+ guids.before = switchguid_before;
+ guids.after = switchguid_after;
+ guids.found = 0;
+ ibnd_iter_nodes_type(fabric,
+ replace_node_guid,
+ IB_NODE_SWITCH,
+ &guids);
+
+ if (!guids.found)
+ IBEXIT("switchguid = %" PRIx64 " not found",
+ switchguid_before);
+ }
+
+ if (caguid_flag) {
+ guids.before = caguid_before;
+ guids.after = caguid_after;
+ guids.found = 0;
+ ibnd_iter_nodes_type(fabric,
+ replace_node_guid,
+ IB_NODE_CA,
+ &guids);
+
+ if (!guids.found)
+ IBEXIT("caguid = %" PRIx64 " not found",
+ caguid_before);
+ }
+
+ if (sysimgguid_flag) {
+ guids.before = sysimgguid_before;
+ guids.after = sysimgguid_after;
+ guids.found = 0;
+ ibnd_iter_nodes(fabric,
+ replace_sysimgguid,
+ &guids);
+
+ if (!guids.found)
+ IBEXIT("sysimgguid = %" PRIx64 " not found",
+ sysimgguid_before);
+ }
+
+ if (portguid_flag) {
+ guids.searchguid = portguid_nodeguid;
+ guids.searchguid_found = 0;
+ guids.before = portguid_before;
+ guids.after = portguid_after;
+ guids.found = 0;
+ ibnd_iter_nodes(fabric,
+ replace_portguid,
+ &guids);
+
+ if (!guids.searchguid_found)
+ IBEXIT("nodeguid = %" PRIx64 " not found",
+ portguid_nodeguid);
+
+ if (!guids.found)
+ IBEXIT("portguid = %" PRIx64 " not found",
+ portguid_before);
+ }
+
+ if (ibnd_cache_fabric(fabric, new_cache_file, 0) < 0)
+ IBEXIT("caching new cache data failed");
+
+ ibnd_destroy_fabric(fabric);
+ exit(0);
+}
diff --git a/contrib/ofed/infiniband-diags/src/ibccconfig.c b/contrib/ofed/infiniband-diags/src/ibccconfig.c
new file mode 100644
index 000000000000..4b6859145bb6
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/src/ibccconfig.c
@@ -0,0 +1,639 @@
+/*
+ * Copyright (c) 2004-2009 Voltaire Inc. All rights reserved.
+ * Copyright (c) 2011 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 2011 Lawrence Livermore National Lab. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <getopt.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <limits.h>
+#include <ctype.h>
+
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
+
+#include <infiniband/mad.h>
+
+#include "ibdiag_common.h"
+
+struct ibmad_port *srcport;
+
+static ibmad_gid_t dgid;
+static int with_grh;
+
+static op_fn_t congestion_key_info;
+static op_fn_t switch_congestion_setting;
+static op_fn_t switch_port_congestion_setting;
+static op_fn_t ca_congestion_setting;
+static op_fn_t congestion_control_table;
+
+static const match_rec_t match_tbl[] = {
+ {"CongestionKeyInfo", "CK", congestion_key_info, 0,
+ "<cckey> <cckeyprotectbit> <cckeyleaseperiod> <cckeyviolations>"},
+ {"SwitchCongestionSetting", "SS", switch_congestion_setting, 0,
+ "<controlmap> <victimmask> <creditmask> <threshold> <packetsize> "
+ "<csthreshold> <csreturndelay> <markingrate>"},
+ {"SwitchPortCongestionSetting", "SP", switch_port_congestion_setting, 1,
+ "<valid> <control_type> <threshold> <packet_size> <cong_parm_marking_rate>"},
+ {"CACongestionSetting", "CS", ca_congestion_setting, 0,
+ "<port_control> <control_map> <ccti_timer> <ccti_increase> "
+ "<trigger_threshold> <ccti_min>"},
+ {"CongestionControlTable", "CT", congestion_control_table, 0,
+ "<cctilimit> <index> <cctentry> <cctentry> ..."},
+ {0}
+};
+
+uint64_t cckey = 0;
+
+/*******************************************/
+static char *parselonglongint(char *arg, uint64_t *val)
+{
+ char *endptr = NULL;
+
+ errno = 0;
+ *val = strtoull(arg, &endptr, 0);
+ if ((endptr && *endptr != '\0')
+ || errno != 0) {
+ if (errno == ERANGE)
+ return "value out of range";
+ return "invalid integer input";
+ }
+
+ return NULL;
+}
+
+static char *parseint(char *arg, uint32_t *val, int hexonly)
+{
+ char *endptr = NULL;
+
+ errno = 0;
+ *val = strtoul(arg, &endptr, hexonly ? 16 : 0);
+ if ((endptr && *endptr != '\0')
+ || errno != 0) {
+ if (errno == ERANGE)
+ return "value out of range";
+ return "invalid integer input";
+ }
+
+ return NULL;
+}
+
+static char *congestion_key_info(ib_portid_t * dest, char **argv, int argc)
+{
+ uint8_t rcv[IB_CC_DATA_SZ] = { 0 };
+ uint8_t payload[IB_CC_DATA_SZ] = { 0 };
+ uint64_t cc_key;
+ uint32_t cc_keyprotectbit;
+ uint32_t cc_keyleaseperiod;
+ uint32_t cc_keyviolations;
+ char *errstr;
+
+ if (argc != 4)
+ return "invalid number of parameters for CongestionKeyInfo";
+
+ if ((errstr = parselonglongint(argv[0], &cc_key)))
+ return errstr;
+ if ((errstr = parseint(argv[1], &cc_keyprotectbit, 0)))
+ return errstr;
+ if ((errstr = parseint(argv[2], &cc_keyleaseperiod, 0)))
+ return errstr;
+ if ((errstr = parseint(argv[3], &cc_keyviolations, 0)))
+ return errstr;
+
+ if (cc_keyprotectbit != 0 && cc_keyprotectbit != 1)
+ return "invalid cc_keyprotectbit value";
+
+ if (cc_keyleaseperiod > USHRT_MAX)
+ return "invalid cc_keyleaseperiod value";
+
+ if (cc_keyviolations > USHRT_MAX)
+ return "invalid cc_keyviolations value";
+
+ mad_set_field64(payload,
+ 0,
+ IB_CC_CONGESTION_KEY_INFO_CC_KEY_F,
+ cc_key);
+
+ mad_encode_field(payload,
+ IB_CC_CONGESTION_KEY_INFO_CC_KEY_PROTECT_BIT_F,
+ &cc_keyprotectbit);
+
+ mad_encode_field(payload,
+ IB_CC_CONGESTION_KEY_INFO_CC_KEY_LEASE_PERIOD_F,
+ &cc_keyleaseperiod);
+
+ /* spec says "setting the counter to a value other than zero results
+ * in the counter being left unchanged. So if user wants no change,
+ * they gotta input non-zero
+ */
+ mad_encode_field(payload,
+ IB_CC_CONGESTION_KEY_INFO_CC_KEY_VIOLATIONS_F,
+ &cc_keyviolations);
+
+ if (!cc_config_status_via(payload, rcv, dest, IB_CC_ATTR_CONGESTION_KEY_INFO,
+ 0, 0, NULL, srcport, cckey))
+ return "congestion key info config failed";
+
+ return NULL;
+}
+
+
+/* parse like it's a hypothetical 256 bit hex code */
+static char *parse256(char *arg, uint8_t *buf)
+{
+ int numdigits = 0;
+ int startindex;
+ char *ptr;
+ int i;
+
+ if (!strncmp(arg, "0x", 2) || !strncmp(arg, "0X", 2))
+ arg += 2;
+
+ for (ptr = arg; *ptr; ptr++) {
+ if (!isxdigit(*ptr))
+ return "invalid hex digit read";
+ numdigits++;
+ }
+
+ if (numdigits > 64)
+ return "hex code too long";
+
+ /* we need to imagine that this is like a 256-bit int stored
+ * in big endian. So we need to find the first index
+ * point where the user's input would start in our array.
+ */
+ startindex = 32 - ((numdigits - 1) / 2) - 1;
+
+ for (i = startindex; i <= 31; i++) {
+ char tmp[3] = { 0 };
+ uint32_t tmpint;
+ char *errstr;
+
+ /* I can't help but think there is a strtoX that
+ * will do this for me, but I can't find it.
+ */
+ if (i == startindex && numdigits % 2) {
+ memcpy(tmp, arg, 1);
+ arg++;
+ }
+ else {
+ memcpy(tmp, arg, 2);
+ arg += 2;
+ }
+
+ if ((errstr = parseint(tmp, &tmpint, 1)))
+ return errstr;
+ buf[i] = tmpint;
+ }
+
+ return NULL;
+}
+
+static char *parsecct(char *arg, uint32_t *shift, uint32_t *multiplier)
+{
+ char buf[1024] = { 0 };
+ char *errstr;
+ char *ptr;
+
+ strcpy(buf, arg);
+
+ if (!(ptr = strchr(buf, ':')))
+ return "ccts are formatted shift:multiplier";
+
+ *ptr = '\0';
+ ptr++;
+
+ if ((errstr = parseint(buf, shift, 0)))
+ return errstr;
+
+ if ((errstr = parseint(ptr, multiplier, 0)))
+ return errstr;
+
+ return NULL;
+}
+
+static char *switch_congestion_setting(ib_portid_t * dest, char **argv, int argc)
+{
+ uint8_t rcv[IB_CC_DATA_SZ] = { 0 };
+ uint8_t payload[IB_CC_DATA_SZ] = { 0 };
+ uint32_t control_map;
+ uint8_t victim_mask[32] = { 0 };
+ uint8_t credit_mask[32] = { 0 };
+ uint32_t threshold;
+ uint32_t packet_size;
+ uint32_t cs_threshold;
+ uint32_t cs_returndelay_s;
+ uint32_t cs_returndelay_m;
+ uint32_t cs_returndelay;
+ uint32_t marking_rate;
+ char *errstr;
+
+ if (argc != 8)
+ return "invalid number of parameters for SwitchCongestionSetting";
+
+ if ((errstr = parseint(argv[0], &control_map, 0)))
+ return errstr;
+
+ if ((errstr = parse256(argv[1], victim_mask)))
+ return errstr;
+
+ if ((errstr = parse256(argv[2], credit_mask)))
+ return errstr;
+
+ if ((errstr = parseint(argv[3], &threshold, 0)))
+ return errstr;
+
+ if ((errstr = parseint(argv[4], &packet_size, 0)))
+ return errstr;
+
+ if ((errstr = parseint(argv[5], &cs_threshold, 0)))
+ return errstr;
+
+ if ((errstr = parsecct(argv[6], &cs_returndelay_s, &cs_returndelay_m)))
+ return errstr;
+
+ cs_returndelay = cs_returndelay_m;
+ cs_returndelay |= (cs_returndelay_s << 14);
+
+ if ((errstr = parseint(argv[7], &marking_rate, 0)))
+ return errstr;
+
+ mad_encode_field(payload,
+ IB_CC_SWITCH_CONGESTION_SETTING_CONTROL_MAP_F,
+ &control_map);
+
+ mad_set_array(payload,
+ 0,
+ IB_CC_SWITCH_CONGESTION_SETTING_VICTIM_MASK_F,
+ victim_mask);
+
+ mad_set_array(payload,
+ 0,
+ IB_CC_SWITCH_CONGESTION_SETTING_CREDIT_MASK_F,
+ credit_mask);
+
+ mad_encode_field(payload,
+ IB_CC_SWITCH_CONGESTION_SETTING_THRESHOLD_F,
+ &threshold);
+
+ mad_encode_field(payload,
+ IB_CC_SWITCH_CONGESTION_SETTING_PACKET_SIZE_F,
+ &packet_size);
+
+ mad_encode_field(payload,
+ IB_CC_SWITCH_CONGESTION_SETTING_CS_THRESHOLD_F,
+ &cs_threshold);
+
+ mad_encode_field(payload,
+ IB_CC_SWITCH_CONGESTION_SETTING_CS_RETURN_DELAY_F,
+ &cs_returndelay);
+
+ mad_encode_field(payload,
+ IB_CC_SWITCH_CONGESTION_SETTING_MARKING_RATE_F,
+ &marking_rate);
+
+ if (!cc_config_status_via(payload, rcv, dest, IB_CC_ATTR_SWITCH_CONGESTION_SETTING,
+ 0, 0, NULL, srcport, cckey))
+ return "switch congestion setting config failed";
+
+ return NULL;
+}
+
+static char *switch_port_congestion_setting(ib_portid_t * dest, char **argv, int argc)
+{
+ uint8_t rcv[IB_CC_DATA_SZ] = { 0 };
+ uint8_t payload[IB_CC_DATA_SZ] = { 0 };
+ uint8_t data[IB_CC_DATA_SZ] = { 0 };
+ uint32_t portnum;
+ uint32_t valid;
+ uint32_t control_type;
+ uint32_t threshold;
+ uint32_t packet_size;
+ uint32_t cong_parm_marking_rate;
+ uint32_t type;
+ uint32_t numports;
+ uint8_t *ptr;
+ char *errstr;
+
+ if (argc != 6)
+ return "invalid number of parameters for SwitchPortCongestion";
+
+ if ((errstr = parseint(argv[0], &portnum, 0)))
+ return errstr;
+
+ if ((errstr = parseint(argv[1], &valid, 0)))
+ return errstr;
+
+ if ((errstr = parseint(argv[2], &control_type, 0)))
+ return errstr;
+
+ if ((errstr = parseint(argv[3], &threshold, 0)))
+ return errstr;
+
+ if ((errstr = parseint(argv[4], &packet_size, 0)))
+ return errstr;
+
+ if ((errstr = parseint(argv[5], &cong_parm_marking_rate, 0)))
+ return errstr;
+
+ /* Figure out number of ports first */
+ if (!smp_query_via(data, dest, IB_ATTR_NODE_INFO, 0, 0, srcport))
+ return "node info config failed";
+
+ mad_decode_field((uint8_t *)data, IB_NODE_TYPE_F, &type);
+ mad_decode_field((uint8_t *)data, IB_NODE_NPORTS_F, &numports);
+
+ if (type != IB_NODE_SWITCH)
+ return "destination not a switch";
+
+ if (portnum > numports)
+ return "invalid port number specified";
+
+ /* We are modifying only 1 port, so get the current config */
+ if (!cc_query_status_via(payload, dest, IB_CC_ATTR_SWITCH_PORT_CONGESTION_SETTING,
+ portnum / 32, 0, NULL, srcport, cckey))
+ return "switch port congestion setting query failed";
+
+ ptr = payload + (((portnum % 32) * 4));
+
+ mad_encode_field(ptr,
+ IB_CC_SWITCH_PORT_CONGESTION_SETTING_ELEMENT_VALID_F,
+ &valid);
+
+ mad_encode_field(ptr,
+ IB_CC_SWITCH_PORT_CONGESTION_SETTING_ELEMENT_CONTROL_TYPE_F,
+ &control_type);
+
+ mad_encode_field(ptr,
+ IB_CC_SWITCH_PORT_CONGESTION_SETTING_ELEMENT_THRESHOLD_F,
+ &threshold);
+
+ mad_encode_field(ptr,
+ IB_CC_SWITCH_PORT_CONGESTION_SETTING_ELEMENT_PACKET_SIZE_F,
+ &packet_size);
+
+ mad_encode_field(ptr,
+ IB_CC_SWITCH_PORT_CONGESTION_SETTING_ELEMENT_CONG_PARM_MARKING_RATE_F,
+ &cong_parm_marking_rate);
+
+ if (!cc_config_status_via(payload, rcv, dest, IB_CC_ATTR_SWITCH_PORT_CONGESTION_SETTING,
+ portnum / 32, 0, NULL, srcport, cckey))
+ return "switch port congestion setting config failed";
+
+ return NULL;
+}
+
+static char *ca_congestion_setting(ib_portid_t * dest, char **argv, int argc)
+{
+ uint8_t rcv[IB_CC_DATA_SZ] = { 0 };
+ uint8_t payload[IB_CC_DATA_SZ] = { 0 };
+ uint32_t port_control;
+ uint32_t control_map;
+ uint32_t ccti_timer;
+ uint32_t ccti_increase;
+ uint32_t trigger_threshold;
+ uint32_t ccti_min;
+ char *errstr;
+ int i;
+
+ if (argc != 6)
+ return "invalid number of parameters for CACongestionSetting";
+
+ if ((errstr = parseint(argv[0], &port_control, 0)))
+ return errstr;
+
+ if ((errstr = parseint(argv[1], &control_map, 0)))
+ return errstr;
+
+ if ((errstr = parseint(argv[2], &ccti_timer, 0)))
+ return errstr;
+
+ if ((errstr = parseint(argv[3], &ccti_increase, 0)))
+ return errstr;
+
+ if ((errstr = parseint(argv[4], &trigger_threshold, 0)))
+ return errstr;
+
+ if ((errstr = parseint(argv[5], &ccti_min, 0)))
+ return errstr;
+
+ mad_encode_field(payload,
+ IB_CC_CA_CONGESTION_SETTING_PORT_CONTROL_F,
+ &port_control);
+
+ mad_encode_field(payload,
+ IB_CC_CA_CONGESTION_SETTING_CONTROL_MAP_F,
+ &control_map);
+
+ for (i = 0; i < 16; i++) {
+ uint8_t *ptr;
+
+ if (!(control_map & (0x1 << i)))
+ continue;
+
+ ptr = payload + 2 + 2 + i * 8;
+
+ mad_encode_field(ptr,
+ IB_CC_CA_CONGESTION_ENTRY_CCTI_TIMER_F,
+ &ccti_timer);
+
+ mad_encode_field(ptr,
+ IB_CC_CA_CONGESTION_ENTRY_CCTI_INCREASE_F,
+ &ccti_increase);
+
+ mad_encode_field(ptr,
+ IB_CC_CA_CONGESTION_ENTRY_TRIGGER_THRESHOLD_F,
+ &trigger_threshold);
+
+ mad_encode_field(ptr,
+ IB_CC_CA_CONGESTION_ENTRY_CCTI_MIN_F,
+ &ccti_min);
+ }
+
+ if (!cc_config_status_via(payload, rcv, dest, IB_CC_ATTR_CA_CONGESTION_SETTING,
+ 0, 0, NULL, srcport, cckey))
+ return "ca congestion setting config failed";
+
+ return NULL;
+}
+
+static char *congestion_control_table(ib_portid_t * dest, char **argv, int argc)
+{
+ uint8_t rcv[IB_CC_DATA_SZ] = { 0 };
+ uint8_t payload[IB_CC_DATA_SZ] = { 0 };
+ uint32_t ccti_limit;
+ uint32_t index;
+ uint32_t cctshifts[64];
+ uint32_t cctmults[64];
+ char *errstr;
+ int i;
+
+ if (argc < 2 || argc > 66)
+ return "invalid number of parameters for CongestionControlTable";
+
+ if ((errstr = parseint(argv[0], &ccti_limit, 0)))
+ return errstr;
+
+ if ((errstr = parseint(argv[1], &index, 0)))
+ return errstr;
+
+ if (ccti_limit && (ccti_limit + 1) != (index * 64 + (argc - 2)))
+ return "invalid number of cct entries input given ccti_limit and index";
+
+ for (i = 0; i < (argc - 2); i++) {
+ if ((errstr = parsecct(argv[i + 2], &cctshifts[i], &cctmults[i])))
+ return errstr;
+ }
+
+ mad_encode_field(payload,
+ IB_CC_CONGESTION_CONTROL_TABLE_CCTI_LIMIT_F,
+ &ccti_limit);
+
+ for (i = 0; i < (argc - 2); i++) {
+ mad_encode_field(payload + 4 + i * 2,
+ IB_CC_CONGESTION_CONTROL_TABLE_ENTRY_CCT_SHIFT_F,
+ &cctshifts[i]);
+
+ mad_encode_field(payload + 4 + i * 2,
+ IB_CC_CONGESTION_CONTROL_TABLE_ENTRY_CCT_MULTIPLIER_F,
+ &cctmults[i]);
+ }
+
+ if (!cc_config_status_via(payload, rcv, dest, IB_CC_ATTR_CONGESTION_CONTROL_TABLE,
+ index, 0, NULL, srcport, cckey))
+ return "congestion control table config failed";
+
+ return NULL;
+}
+
+static int process_opt(void *context, int ch, char *optarg)
+{
+ switch (ch) {
+ case 'c':
+ cckey = (uint64_t) strtoull(optarg, 0, 0);
+ break;
+ case 25:
+ if (!inet_pton(AF_INET6, optarg, &dgid)) {
+ fprintf(stderr, "dgid format is wrong!\n");
+ ibdiag_show_usage();
+ return 1;
+ }
+ with_grh = 1;
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ char usage_args[1024];
+ int mgmt_classes[3] = { IB_SMI_CLASS, IB_SA_CLASS, IB_CC_CLASS };
+ ib_portid_t portid = { 0 };
+ char *err;
+ op_fn_t *fn;
+ const match_rec_t *r;
+ int n;
+
+ const struct ibdiag_opt opts[] = {
+ {"cckey", 'c', 1, "<key>", "CC key"},
+ {"dgid", 25, 1, NULL, "remote gid (IPv6 format)"},
+ {0}
+ };
+ const char *usage_examples[] = {
+ "SwitchCongestionSetting 2 0x1F 0x1FFFFFFFFF 0x0 0xF 8 0 0:0 1\t# Configure Switch Congestion Settings",
+ "CACongestionSetting 1 0 0x3 150 1 0 0\t\t# Configure CA Congestion Settings to SL 0 and SL 1",
+ "CACongestionSetting 1 0 0x4 200 1 0 0\t\t# Configure CA Congestion Settings to SL 2",
+ "CongestionControlTable 1 63 0 0:0 0:1 ...\t# Configure first block of Congestion Control Table",
+ "CongestionControlTable 1 127 0 0:64 0:65 ...\t# Configure second block of Congestion Control Table",
+ NULL
+ };
+
+ n = sprintf(usage_args, "[-c key] <op> <lid|guid>\n"
+ "\nWARNING -- You should understand what you are "
+ "doing before using this tool. Misuse of this "
+ "tool could result in a broken fabric.\n"
+ "\nSupported ops (and aliases, case insensitive):\n");
+ for (r = match_tbl; r->name; r++) {
+ n += snprintf(usage_args + n, sizeof(usage_args) - n,
+ " %s (%s) <lid|guid>%s%s%s\n", r->name,
+ r->alias ? r->alias : "",
+ r->opt_portnum ? " <portnum>" : "",
+ r->ops_extra ? " " : "",
+ r->ops_extra ? r->ops_extra : "");
+ if (n >= sizeof(usage_args))
+ exit(-1);
+ }
+
+ ibdiag_process_opts(argc, argv, NULL, "DK", opts, process_opt,
+ usage_args, usage_examples);
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 2)
+ ibdiag_show_usage();
+
+ if (!(fn = match_op(match_tbl, argv[0])))
+ IBEXIT("operation '%s' not supported", argv[0]);
+
+ srcport = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 3);
+ if (!srcport)
+ IBEXIT("Failed to open '%s' port '%d'", ibd_ca, ibd_ca_port);
+
+ smp_mkey_set(srcport, ibd_mkey);
+
+ if (with_grh && ibd_dest_type != IB_DEST_LID)
+ IBEXIT("When using GRH, LID should be provided");
+ if (resolve_portid_str(ibd_ca, ibd_ca_port, &portid, argv[1],
+ ibd_dest_type, ibd_sm_id, srcport) < 0)
+ IBEXIT("can't resolve destination %s", argv[1]);
+ if (with_grh) {
+ portid.grh_present = 1;
+ memcpy(&portid.gid, &dgid, sizeof(portid.gid));
+ }
+ if ((err = fn(&portid, argv + 2, argc - 2)))
+ IBEXIT("operation %s: %s", argv[0], err);
+
+ mad_rpc_close_port(srcport);
+ exit(0);
+}
diff --git a/contrib/ofed/infiniband-diags/src/ibccquery.c b/contrib/ofed/infiniband-diags/src/ibccquery.c
new file mode 100644
index 000000000000..ed77dc515d66
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/src/ibccquery.c
@@ -0,0 +1,427 @@
+/*
+ * Copyright (c) 2004-2009 Voltaire Inc. All rights reserved.
+ * Copyright (c) 2011 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 2011 Lawrence Livermore National Lab. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <getopt.h>
+#include <netinet/in.h>
+
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
+
+#include <infiniband/mad.h>
+
+#include "ibdiag_common.h"
+
+struct ibmad_port *srcport;
+
+static ibmad_gid_t dgid;
+static int with_grh;
+
+static op_fn_t class_port_info;
+static op_fn_t congestion_info;
+static op_fn_t congestion_key_info;
+static op_fn_t congestion_log;
+static op_fn_t switch_congestion_setting;
+static op_fn_t switch_port_congestion_setting;
+static op_fn_t ca_congestion_setting;
+static op_fn_t congestion_control_table;
+static op_fn_t timestamp_dump;
+
+static const match_rec_t match_tbl[] = {
+ {"ClassPortInfo", "CP", class_port_info, 0, ""},
+ {"CongestionInfo", "CI", congestion_info, 0, ""},
+ {"CongestionKeyInfo", "CK", congestion_key_info, 0, ""},
+ {"CongestionLog", "CL", congestion_log, 0, ""},
+ {"SwitchCongestionSetting", "SS", switch_congestion_setting, 0, ""},
+ {"SwitchPortCongestionSetting", "SP", switch_port_congestion_setting, 1, ""},
+ {"CACongestionSetting", "CS", ca_congestion_setting, 0, ""},
+ {"CongestionControlTable", "CT", congestion_control_table, 0, ""},
+ {"Timestamp", "TI", timestamp_dump, 0, ""},
+ {0}
+};
+
+uint64_t cckey = 0;
+
+/*******************************************/
+static char *class_port_info(ib_portid_t * dest, char **argv, int argc)
+{
+ char buf[2048];
+ char data[IB_CC_DATA_SZ] = { 0 };
+
+ if (!cc_query_status_via(data, dest, CLASS_PORT_INFO,
+ 0, 0, NULL, srcport, cckey))
+ return "class port info query failed";
+
+ mad_dump_classportinfo(buf, sizeof buf, data, sizeof data);
+
+ printf("# ClassPortInfo: %s\n%s", portid2str(dest), buf);
+ return NULL;
+}
+
+static char *congestion_info(ib_portid_t * dest, char **argv, int argc)
+{
+ char buf[2048];
+ char data[IB_CC_DATA_SZ] = { 0 };
+
+ if (!cc_query_status_via(data, dest, IB_CC_ATTR_CONGESTION_INFO,
+ 0, 0, NULL, srcport, cckey))
+ return "congestion info query failed";
+
+ mad_dump_cc_congestioninfo(buf, sizeof buf, data, sizeof data);
+
+ printf("# CongestionInfo: %s\n%s", portid2str(dest), buf);
+ return NULL;
+}
+
+static char *congestion_key_info(ib_portid_t * dest, char **argv, int argc)
+{
+ char buf[2048];
+ char data[IB_CC_DATA_SZ] = { 0 };
+
+ if (!cc_query_status_via(data, dest, IB_CC_ATTR_CONGESTION_KEY_INFO,
+ 0, 0, NULL, srcport, cckey))
+ return "congestion key info query failed";
+
+ mad_dump_cc_congestionkeyinfo(buf, sizeof buf, data, sizeof data);
+
+ printf("# CongestionKeyInfo: %s\n%s", portid2str(dest), buf);
+ return NULL;
+}
+
+static char *congestion_log(ib_portid_t * dest, char **argv, int argc)
+{
+ char buf[2048];
+ char data[IB_CC_LOG_DATA_SZ] = { 0 };
+ char emptybuf[16] = { 0 };
+ int i, type;
+
+ if (!cc_query_status_via(data, dest, IB_CC_ATTR_CONGESTION_LOG,
+ 0, 0, NULL, srcport, cckey))
+ return "congestion log query failed";
+
+ mad_decode_field((uint8_t *)data, IB_CC_CONGESTION_LOG_LOGTYPE_F, &type);
+
+ if (type != 1 && type != 2)
+ return "unrecognized log type";
+
+ mad_dump_cc_congestionlog(buf, sizeof buf, data, sizeof data);
+
+ printf("# CongestionLog: %s\n%s", portid2str(dest), buf);
+
+ if (type == 1) {
+ mad_dump_cc_congestionlogswitch(buf, sizeof buf, data, sizeof data);
+ printf("%s\n", buf);
+ for (i = 0; i < 15; i++) {
+ /* output only if entry not 0 */
+ if (memcmp(data + 40 + i * 12, emptybuf, 12)) {
+ mad_dump_cc_congestionlogentryswitch(buf, sizeof buf,
+ data + 40 + i * 12,
+ 12);
+ printf("%s\n", buf);
+ }
+ }
+ }
+ else {
+ /* XXX: Q3/2010 errata lists first entry offset at 80, but we assume
+ * will be updated to 96 once CurrentTimeStamp field is word aligned.
+ * In addition, assume max 13 log events instead of 16. Due to
+ * errata changes increasing size of CA log event, 16 log events is
+ * no longer possible to fit in max MAD size.
+ */
+ mad_dump_cc_congestionlogca(buf, sizeof buf, data, sizeof data);
+ printf("%s\n", buf);
+ for (i = 0; i < 13; i++) {
+ /* output only if entry not 0 */
+ if (memcmp(data + 12 + i * 16, emptybuf, 16)) {
+ mad_dump_cc_congestionlogentryca(buf, sizeof buf,
+ data + 12 + i * 16,
+ 16);
+ printf("%s\n", buf);
+ }
+ }
+ }
+
+ return NULL;
+}
+
+static char *switch_congestion_setting(ib_portid_t * dest, char **argv, int argc)
+{
+ char buf[2048];
+ char data[IB_CC_DATA_SZ] = { 0 };
+
+ if (!cc_query_status_via(data, dest, IB_CC_ATTR_SWITCH_CONGESTION_SETTING,
+ 0, 0, NULL, srcport, cckey))
+ return "switch congestion setting query failed";
+
+ mad_dump_cc_switchcongestionsetting(buf, sizeof buf, data, sizeof data);
+
+ printf("# SwitchCongestionSetting: %s\n%s", portid2str(dest), buf);
+ return NULL;
+}
+
+static char *switch_port_congestion_setting(ib_portid_t * dest, char **argv, int argc)
+{
+ char buf[2048];
+ char data[IB_CC_DATA_SZ] = { 0 };
+ int type, numports, maxblocks, i, j;
+ int portnum = 0;
+ int outputcount = 0;
+
+ if (argc > 0)
+ portnum = strtol(argv[0], 0, 0);
+
+ /* Figure out number of ports first */
+ if (!smp_query_via(data, dest, IB_ATTR_NODE_INFO, 0, 0, srcport))
+ return "node info query failed";
+
+ mad_decode_field((uint8_t *)data, IB_NODE_TYPE_F, &type);
+ mad_decode_field((uint8_t *)data, IB_NODE_NPORTS_F, &numports);
+
+ if (type != IB_NODE_SWITCH)
+ return "destination not a switch";
+
+ printf("# SwitchPortCongestionSetting: %s\n", portid2str(dest));
+
+ if (portnum) {
+ if (portnum > numports)
+ return "invalid port number specified";
+
+ memset(data, '\0', sizeof data);
+ if (!cc_query_status_via(data, dest, IB_CC_ATTR_SWITCH_PORT_CONGESTION_SETTING,
+ portnum / 32, 0, NULL, srcport, cckey))
+ return "switch port congestion setting query failed";
+
+ mad_dump_cc_switchportcongestionsettingelement(buf, sizeof buf,
+ data + ((portnum % 32) * 4),
+ 4);
+ printf("%s", buf);
+ return NULL;
+ }
+
+ /* else get all port info */
+
+ maxblocks = numports / 32 + 1;
+
+ for (i = 0; i < maxblocks; i++) {
+ memset(data, '\0', sizeof data);
+ if (!cc_query_status_via(data, dest, IB_CC_ATTR_SWITCH_PORT_CONGESTION_SETTING,
+ i, 0, NULL, srcport, cckey))
+ return "switch port congestion setting query failed";
+
+ for (j = 0; j < 32 && outputcount <= numports; j++) {
+ printf("Port:............................%u\n", i * 32 + j);
+ mad_dump_cc_switchportcongestionsettingelement(buf, sizeof buf,
+ data + j * 4,
+ 4);
+ printf("%s\n", buf);
+ outputcount++;
+ }
+ }
+
+ return NULL;
+}
+
+static char *ca_congestion_setting(ib_portid_t * dest, char **argv, int argc)
+{
+ char buf[2048];
+ char data[IB_CC_DATA_SZ] = { 0 };
+ int i;
+
+ if (!cc_query_status_via(data, dest, IB_CC_ATTR_CA_CONGESTION_SETTING,
+ 0, 0, NULL, srcport, cckey))
+ return "ca congestion setting query failed";
+
+ mad_dump_cc_cacongestionsetting(buf, sizeof buf, data, sizeof data);
+
+ printf("# CACongestionSetting: %s\n%s\n", portid2str(dest), buf);
+
+ for (i = 0; i < 16; i++) {
+ printf("SL:..............................%u\n", i);
+ mad_dump_cc_cacongestionentry(buf, sizeof buf,
+ data + 4 + i * 8,
+ 8);
+ printf("%s\n", buf);
+ }
+ return NULL;
+}
+
+static char *congestion_control_table(ib_portid_t * dest, char **argv, int argc)
+{
+ char buf[2048];
+ char data[IB_CC_DATA_SZ] = { 0 };
+ int limit, outputcount = 0;
+ int i, j;
+
+ if (!cc_query_status_via(data, dest, IB_CC_ATTR_CONGESTION_CONTROL_TABLE,
+ 0, 0, NULL, srcport, cckey))
+ return "congestion control table query failed";
+
+ mad_decode_field((uint8_t *)data, IB_CC_CONGESTION_CONTROL_TABLE_CCTI_LIMIT_F, &limit);
+
+ mad_dump_cc_congestioncontroltable(buf, sizeof buf, data, sizeof data);
+
+ printf("# CongestionControlTable: %s\n%s\n", portid2str(dest), buf);
+
+ if (!limit)
+ return NULL;
+
+ for (i = 0; i < (limit/64) + 1; i++) {
+
+ /* first query done */
+ if (i)
+ if (!cc_query_status_via(data, dest, IB_CC_ATTR_CONGESTION_CONTROL_TABLE,
+ i, 0, NULL, srcport, cckey))
+ return "congestion control table query failed";
+
+ for (j = 0; j < 64 && outputcount <= limit; j++) {
+ printf("Entry:...........................%u\n", i*64 + j);
+ mad_dump_cc_congestioncontroltableentry(buf, sizeof buf,
+ data + 4 + j * 2,
+ sizeof data - 4 - j * 2);
+ printf("%s\n", buf);
+ outputcount++;
+ }
+ }
+ return NULL;
+}
+
+static char *timestamp_dump(ib_portid_t * dest, char **argv, int argc)
+{
+ char buf[2048];
+ char data[IB_CC_DATA_SZ] = { 0 };
+
+ if (!cc_query_status_via(data, dest, IB_CC_ATTR_TIMESTAMP,
+ 0, 0, NULL, srcport, cckey))
+ return "timestamp query failed";
+
+ mad_dump_cc_timestamp(buf, sizeof buf, data, sizeof data);
+
+ printf("# Timestamp: %s\n%s", portid2str(dest), buf);
+ return NULL;
+}
+
+static int process_opt(void *context, int ch, char *optarg)
+{
+ switch (ch) {
+ case 'c':
+ cckey = (uint64_t) strtoull(optarg, 0, 0);
+ break;
+ case 25:
+ if (!inet_pton(AF_INET6, optarg, &dgid)) {
+ fprintf(stderr, "dgid format is wrong!\n");
+ ibdiag_show_usage();
+ return 1;
+ }
+ with_grh = 1;
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ char usage_args[1024];
+ int mgmt_classes[3] = { IB_SMI_CLASS, IB_SA_CLASS, IB_CC_CLASS };
+ ib_portid_t portid = { 0 };
+ char *err;
+ op_fn_t *fn;
+ const match_rec_t *r;
+ int n;
+
+ const struct ibdiag_opt opts[] = {
+ {"cckey", 'c', 1, "<key>", "CC key"},
+ {"dgid", 25, 1, NULL, "remote gid (IPv6 format)"},
+ {0}
+ };
+ const char *usage_examples[] = {
+ "CongestionInfo 3\t\t\t# Congestion Info by lid",
+ "SwitchPortCongestionSetting 3\t# Query all Switch Port Congestion Settings",
+ "SwitchPortCongestionSetting 3 1\t# Query Switch Port Congestion Setting for port 1",
+ NULL
+ };
+
+ n = sprintf(usage_args, "[-c key] <op> <lid|guid>\n"
+ "\nSupported ops (and aliases, case insensitive):\n");
+ for (r = match_tbl; r->name; r++) {
+ n += snprintf(usage_args + n, sizeof(usage_args) - n,
+ " %s (%s) <lid|guid>%s\n", r->name,
+ r->alias ? r->alias : "",
+ r->opt_portnum ? " [<portnum>]" : "");
+ if (n >= sizeof(usage_args))
+ exit(-1);
+ }
+
+ ibdiag_process_opts(argc, argv, NULL, "DK", opts, process_opt,
+ usage_args, usage_examples);
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 2)
+ ibdiag_show_usage();
+
+ if (!(fn = match_op(match_tbl, argv[0])))
+ IBEXIT("operation '%s' not supported", argv[0]);
+
+ srcport = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 3);
+ if (!srcport)
+ IBEXIT("Failed to open '%s' port '%d'", ibd_ca, ibd_ca_port);
+
+ smp_mkey_set(srcport, ibd_mkey);
+
+ if (with_grh && ibd_dest_type != IB_DEST_LID)
+ IBEXIT("When using GRH, LID should be provided");
+ if (resolve_portid_str(ibd_ca, ibd_ca_port, &portid, argv[1],
+ ibd_dest_type, ibd_sm_id, srcport) < 0)
+ IBEXIT("can't resolve destination %s", argv[1]);
+ if (with_grh) {
+ portid.grh_present = 1;
+ memcpy(&portid.gid, &dgid, sizeof(portid.gid));
+ }
+ if ((err = fn(&portid, argv + 2, argc - 2)))
+ IBEXIT("operation %s: %s", argv[0], err);
+
+ mad_rpc_close_port(srcport);
+ exit(0);
+}
diff --git a/contrib/ofed/infiniband-diags/src/ibdiag_common.c b/contrib/ofed/infiniband-diags/src/ibdiag_common.c
new file mode 100644
index 000000000000..d668b7ef0557
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/src/ibdiag_common.c
@@ -0,0 +1,940 @@
+/*
+ * Copyright (c) 2006-2007 The Regents of the University of California.
+ * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2010 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ * Copyright (c) 2009 HNR Consulting. All rights reserved.
+ * Copyright (c) 2011 Lawrence Livermore National Security. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+/**
+ * Define common functions which can be included in the various C based diags.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <config.h>
+#include <getopt.h>
+#include <limits.h>
+#include <sys/stat.h>
+#include <stdarg.h>
+
+#include <infiniband/umad.h>
+#include <infiniband/mad.h>
+#include <ibdiag_common.h>
+#include <ibdiag_version.h>
+
+int ibverbose;
+enum MAD_DEST ibd_dest_type = IB_DEST_LID;
+ib_portid_t *ibd_sm_id;
+static ib_portid_t sm_portid = { 0 };
+
+/* general config options */
+#define IBDIAG_CONFIG_GENERAL IBDIAG_CONFIG_PATH"/ibdiag.conf"
+char *ibd_ca = NULL;
+int ibd_ca_port = 0;
+int ibd_timeout = 0;
+uint32_t ibd_ibnetdisc_flags = IBND_CONFIG_MLX_EPI;
+uint64_t ibd_mkey;
+uint64_t ibd_sakey = 0;
+int show_keys = 0;
+char *ibd_nd_format = NULL;
+
+static const char *prog_name;
+static const char *prog_args;
+static const char **prog_examples;
+static struct option *long_opts = NULL;
+static const struct ibdiag_opt *opts_map[256];
+
+static const char *get_build_version(void)
+{
+ return "BUILD VERSION: " IBDIAG_VERSION " Build date: " __DATE__ " "
+ __TIME__;
+}
+
+static void pretty_print(int start, int width, const char *str)
+{
+ int len = width - start;
+ const char *p, *e;
+
+ while (1) {
+ while (isspace(*str))
+ str++;
+ p = str;
+ do {
+ e = p + 1;
+ p = strchr(e, ' ');
+ } while (p && p - str < len);
+ if (!p) {
+ fprintf(stderr, "%s", str);
+ break;
+ }
+ if (e - str == 1)
+ e = p;
+ fprintf(stderr, "%.*s\n%*s", (int)(e - str), str, start, "");
+ str = e;
+ }
+}
+
+static inline int val_str_true(const char *val_str)
+{
+ return ((strncmp(val_str, "TRUE", strlen("TRUE")) == 0) ||
+ (strncmp(val_str, "true", strlen("true")) == 0));
+}
+
+void read_ibdiag_config(const char *file)
+{
+ char buf[1024];
+ FILE *config_fd = NULL;
+ char *p_prefix, *p_last;
+ char *name;
+ char *val_str;
+ struct stat statbuf;
+
+ /* silently ignore missing config file */
+ if (stat(file, &statbuf))
+ return;
+
+ config_fd = fopen(file, "r");
+ if (!config_fd)
+ return;
+
+ while (fgets(buf, sizeof buf, config_fd) != NULL) {
+ p_prefix = strtok_r(buf, "\n", &p_last);
+ if (!p_prefix)
+ continue; /* ignore blank lines */
+
+ if (*p_prefix == '#')
+ continue; /* ignore comment lines */
+
+ name = strtok_r(p_prefix, "=", &p_last);
+ val_str = strtok_r(NULL, "\n", &p_last);
+
+ if (strncmp(name, "CA", strlen("CA")) == 0) {
+ free(ibd_ca);
+ ibd_ca = strdup(val_str);
+ } else if (strncmp(name, "Port", strlen("Port")) == 0) {
+ ibd_ca_port = strtoul(val_str, NULL, 0);
+ } else if (strncmp(name, "timeout", strlen("timeout")) == 0) {
+ ibd_timeout = strtoul(val_str, NULL, 0);
+ } else if (strncmp(name, "MLX_EPI", strlen("MLX_EPI")) == 0) {
+ if (val_str_true(val_str)) {
+ ibd_ibnetdisc_flags |= IBND_CONFIG_MLX_EPI;
+ } else {
+ ibd_ibnetdisc_flags &= ~IBND_CONFIG_MLX_EPI;
+ }
+ } else if (strncmp(name, "m_key", strlen("m_key")) == 0) {
+ ibd_mkey = strtoull(val_str, 0, 0);
+ } else if (strncmp(name, "sa_key",
+ strlen("sa_key")) == 0) {
+ ibd_sakey = strtoull(val_str, 0, 0);
+ } else if (strncmp(name, "nd_format",
+ strlen("nd_format")) == 0) {
+ ibd_nd_format = strdup(val_str);
+ }
+ }
+
+ fclose(config_fd);
+}
+
+
+void ibdiag_show_usage()
+{
+ struct option *o = long_opts;
+ int n;
+
+ fprintf(stderr, "\nUsage: %s [options] %s\n\n", prog_name,
+ prog_args ? prog_args : "");
+
+ if (long_opts[0].name)
+ fprintf(stderr, "Options:\n");
+ for (o = long_opts; o->name; o++) {
+ const struct ibdiag_opt *io = opts_map[o->val];
+ n = fprintf(stderr, " --%s", io->name);
+ if (isprint(io->letter))
+ n += fprintf(stderr, ", -%c", io->letter);
+ if (io->has_arg)
+ n += fprintf(stderr, " %s",
+ io->arg_tmpl ? io->arg_tmpl : "<val>");
+ if (io->description && *io->description) {
+ n += fprintf(stderr, "%*s ", 24 - n > 0 ? 24 - n : 0,
+ "");
+ pretty_print(n, 74, io->description);
+ }
+ fprintf(stderr, "\n");
+ }
+
+ if (prog_examples) {
+ const char **p;
+ fprintf(stderr, "\nExamples:\n");
+ for (p = prog_examples; *p && **p; p++)
+ fprintf(stderr, " %s %s\n", prog_name, *p);
+ }
+
+ fprintf(stderr, "\n");
+
+ exit(2);
+}
+
+static int process_opt(int ch, char *optarg)
+{
+ char *endp;
+ long val;
+
+ switch (ch) {
+ case 'z':
+ read_ibdiag_config(optarg);
+ break;
+ case 'h':
+ ibdiag_show_usage();
+ break;
+ case 'V':
+ fprintf(stderr, "%s %s\n", prog_name, get_build_version());
+ exit(0);
+ case 'e':
+ madrpc_show_errors(1);
+ break;
+ case 'v':
+ ibverbose++;
+ break;
+ case 'd':
+ ibdebug++;
+ madrpc_show_errors(1);
+ umad_debug(ibdebug - 1);
+ break;
+ case 'C':
+ ibd_ca = optarg;
+ break;
+ case 'P':
+ ibd_ca_port = strtoul(optarg, 0, 0);
+ if (ibd_ca_port < 0)
+ IBEXIT("cannot resolve CA port %d", ibd_ca_port);
+ break;
+ case 'D':
+ ibd_dest_type = IB_DEST_DRPATH;
+ break;
+ case 'L':
+ ibd_dest_type = IB_DEST_LID;
+ break;
+ case 'G':
+ ibd_dest_type = IB_DEST_GUID;
+ break;
+ case 't':
+ errno = 0;
+ val = strtol(optarg, &endp, 0);
+ if (errno || (endp && *endp != '\0') || val <= 0 ||
+ val > INT_MAX)
+ IBEXIT("Invalid timeout \"%s\". Timeout requires a "
+ "positive integer value < %d.", optarg, INT_MAX);
+ else {
+ madrpc_set_timeout((int)val);
+ ibd_timeout = (int)val;
+ }
+ break;
+ case 's':
+ /* srcport is not required when resolving via IB_DEST_LID */
+ if (resolve_portid_str(ibd_ca, ibd_ca_port, &sm_portid, optarg,
+ IB_DEST_LID, 0, NULL) < 0)
+ IBEXIT("cannot resolve SM destination port %s",
+ optarg);
+ ibd_sm_id = &sm_portid;
+ break;
+ case 'K':
+ show_keys = 1;
+ break;
+ case 'y':
+ errno = 0;
+ ibd_mkey = strtoull(optarg, &endp, 0);
+ if (errno || *endp != '\0') {
+ errno = 0;
+ ibd_mkey = strtoull(getpass("M_Key: "), &endp, 0);
+ if (errno || *endp != '\0') {
+ IBEXIT("Bad M_Key");
+ }
+ }
+ break;
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+static const struct ibdiag_opt common_opts[] = {
+ {"config", 'z', 1, "<config>", "use config file, default: " IBDIAG_CONFIG_GENERAL},
+ {"Ca", 'C', 1, "<ca>", "Ca name to use"},
+ {"Port", 'P', 1, "<port>", "Ca port number to use"},
+ {"Direct", 'D', 0, NULL, "use Direct address argument"},
+ {"Lid", 'L', 0, NULL, "use LID address argument"},
+ {"Guid", 'G', 0, NULL, "use GUID address argument"},
+ {"timeout", 't', 1, "<ms>", "timeout in ms"},
+ {"sm_port", 's', 1, "<lid>", "SM port lid"},
+ {"show_keys", 'K', 0, NULL, "display security keys in output"},
+ {"m_key", 'y', 1, "<key>", "M_Key to use in request"},
+ {"errors", 'e', 0, NULL, "show send and receive errors"},
+ {"verbose", 'v', 0, NULL, "increase verbosity level"},
+ {"debug", 'd', 0, NULL, "raise debug level"},
+ {"help", 'h', 0, NULL, "help message"},
+ {"version", 'V', 0, NULL, "show version"},
+ {0}
+};
+
+static void make_opt(struct option *l, const struct ibdiag_opt *o,
+ const struct ibdiag_opt *map[])
+{
+ l->name = o->name;
+ l->has_arg = o->has_arg;
+ l->flag = NULL;
+ l->val = o->letter;
+ if (!map[l->val])
+ map[l->val] = o;
+}
+
+static struct option *make_long_opts(const char *exclude_str,
+ const struct ibdiag_opt *custom_opts,
+ const struct ibdiag_opt *map[])
+{
+ struct option *long_opts, *l;
+ const struct ibdiag_opt *o;
+ unsigned n = 0;
+
+ if (custom_opts)
+ for (o = custom_opts; o->name; o++)
+ n++;
+
+ long_opts = malloc((sizeof(common_opts) / sizeof(common_opts[0]) + n) *
+ sizeof(*long_opts));
+ if (!long_opts)
+ return NULL;
+
+ l = long_opts;
+
+ if (custom_opts)
+ for (o = custom_opts; o->name; o++)
+ make_opt(l++, o, map);
+
+ for (o = common_opts; o->name; o++) {
+ if (exclude_str && strchr(exclude_str, o->letter))
+ continue;
+ make_opt(l++, o, map);
+ }
+
+ memset(l, 0, sizeof(*l));
+
+ return long_opts;
+}
+
+static void make_str_opts(const struct option *o, char *p, unsigned size)
+{
+ unsigned i, n = 0;
+
+ for (n = 0; o->name && n + 2 + o->has_arg < size; o++) {
+ p[n++] = (char)o->val;
+ for (i = 0; i < (unsigned)o->has_arg; i++)
+ p[n++] = ':';
+ }
+ p[n] = '\0';
+}
+
+int ibdiag_process_opts(int argc, char *const argv[], void *cxt,
+ const char *exclude_common_str,
+ const struct ibdiag_opt custom_opts[],
+ int (*custom_handler) (void *cxt, int val,
+ char *optarg),
+ const char *usage_args, const char *usage_examples[])
+{
+ char str_opts[1024];
+ const struct ibdiag_opt *o;
+
+ prog_name = argv[0];
+ prog_args = usage_args;
+ prog_examples = usage_examples;
+
+ if (long_opts)
+ free(long_opts);
+
+ long_opts = make_long_opts(exclude_common_str, custom_opts, opts_map);
+ if (!long_opts)
+ return -1;
+
+ read_ibdiag_config(IBDIAG_CONFIG_GENERAL);
+
+ make_str_opts(long_opts, str_opts, sizeof(str_opts));
+
+ while (1) {
+ int ch = getopt_long(argc, argv, str_opts, long_opts, NULL);
+ if (ch == -1)
+ break;
+ o = opts_map[ch];
+ if (!o)
+ ibdiag_show_usage();
+ if (custom_handler) {
+ if (custom_handler(cxt, ch, optarg) &&
+ process_opt(ch, optarg))
+ ibdiag_show_usage();
+ } else if (process_opt(ch, optarg))
+ ibdiag_show_usage();
+ }
+
+ return 0;
+}
+
+void ibexit(const char *fn, char *msg, ...)
+{
+ char buf[512];
+ va_list va;
+ int n;
+
+ va_start(va, msg);
+ n = vsprintf(buf, msg, va);
+ va_end(va);
+ buf[n] = 0;
+
+ if (ibdebug)
+ printf("%s: iberror: [pid %d] %s: failed: %s\n",
+ prog_name ? prog_name : "", getpid(), fn, buf);
+ else
+ printf("%s: iberror: failed: %s\n",
+ prog_name ? prog_name : "", buf);
+
+ exit(-1);
+}
+
+char *
+conv_cnt_human_readable(uint64_t val64, float *val, int data)
+{
+ uint64_t tmp = val64;
+ int ui = 0;
+ int div = 1;
+
+ tmp /= 1024;
+ while (tmp) {
+ ui++;
+ tmp /= 1024;
+ div *= 1024;
+ }
+
+ *val = (float)(val64);
+ if (data) {
+ *val *= 4;
+ if (*val/div > 1024) {
+ ui++;
+ div *= 1024;
+ }
+ }
+ *val /= div;
+
+ if (data) {
+ switch (ui) {
+ case 0:
+ return ("B");
+ case 1:
+ return ("KB");
+ case 2:
+ return ("MB");
+ case 3:
+ return ("GB");
+ case 4:
+ return ("TB");
+ case 5:
+ return ("PB");
+ case 6:
+ return ("EB");
+ default:
+ return ("");
+ }
+ } else {
+ switch (ui) {
+ case 0:
+ return ("");
+ case 1:
+ return ("K");
+ case 2:
+ return ("M");
+ case 3:
+ return ("G");
+ case 4:
+ return ("T");
+ case 5:
+ return ("P");
+ case 6:
+ return ("E");
+ default:
+ return ("");
+ }
+ }
+ return ("");
+}
+
+int is_port_info_extended_supported(ib_portid_t * dest, int port,
+ struct ibmad_port *srcport)
+{
+ uint8_t data[IB_SMP_DATA_SIZE] = { 0 };
+ uint32_t cap_mask;
+ uint16_t cap_mask2;
+
+ if (!smp_query_via(data, dest, IB_ATTR_PORT_INFO, port, 0, srcport))
+ IBEXIT("port info query failed");
+
+ mad_decode_field(data, IB_PORT_CAPMASK_F, &cap_mask);
+ if (cap_mask & CL_NTOH32(IB_PORT_CAP_HAS_CAP_MASK2)) {
+ mad_decode_field(data, IB_PORT_CAPMASK2_F, &cap_mask2);
+ if (!(cap_mask2 &
+ CL_NTOH16(IB_PORT_CAP2_IS_PORT_INFO_EXT_SUPPORTED))) {
+ IBWARN("port info capability mask2 = 0x%x doesn't"
+ " indicate PortInfoExtended support", cap_mask2);
+ return 0;
+ }
+ } else {
+ IBWARN("port info capability mask2 not supported");
+ return 0;
+ }
+
+ return 1;
+}
+
+int is_mlnx_ext_port_info_supported(uint32_t vendorid,
+ uint16_t devid)
+{
+ if (ibd_ibnetdisc_flags & IBND_CONFIG_MLX_EPI) {
+
+ if ((devid >= 0xc738 && devid <= 0xc73b) || devid == 0xcb20 || devid == 0xcf08 ||
+ ((vendorid == 0x119f) &&
+ /* Bull SwitchX */
+ (devid == 0x1b02 || devid == 0x1b50 ||
+ /* Bull SwitchIB and SwitchIB2 */
+ devid == 0x1ba0 ||
+ (devid >= 0x1bd0 && devid <= 0x1bd5))))
+ return 1;
+ if ((devid >= 0x1003 && devid <= 0x1017) ||
+ ((vendorid == 0x119f) &&
+ /* Bull ConnectX3 */
+ (devid == 0x1b33 || devid == 0x1b73 ||
+ devid == 0x1b40 || devid == 0x1b41 ||
+ devid == 0x1b60 || devid == 0x1b61 ||
+ /* Bull ConnectIB */
+ devid == 0x1b83 ||
+ devid == 0x1b93 || devid == 0x1b94 ||
+ /* Bull ConnectX4 */
+ devid == 0x1bb4 || devid == 0x1bb5 ||
+ devid == 0x1bc4)))
+ return 1;
+ }
+
+ return 0;
+}
+
+/** =========================================================================
+ * Resolve the SM portid using the umad layer rather than using
+ * ib_resolve_smlid_via which requires a PortInfo query on the local port.
+ */
+int resolve_sm_portid(char *ca_name, uint8_t portnum, ib_portid_t *sm_id)
+{
+ umad_port_t port;
+ int rc;
+
+ if (!sm_id)
+ return (-1);
+
+ if ((rc = umad_get_port(ca_name, portnum, &port)) < 0)
+ return rc;
+
+ memset(sm_id, 0, sizeof(*sm_id));
+ sm_id->lid = port.sm_lid;
+ sm_id->sl = port.sm_sl;
+
+ umad_release_port(&port);
+
+ return 0;
+}
+
+/** =========================================================================
+ * Resolve local CA characteristics using the umad layer rather than using
+ * ib_resolve_self_via which requires SMP queries on the local port.
+ */
+int resolve_self(char *ca_name, uint8_t ca_port, ib_portid_t *portid,
+ int *portnum, ibmad_gid_t *gid)
+{
+ umad_port_t port;
+ uint64_t prefix, guid;
+ int rc;
+
+ if (!(portid || portnum || gid))
+ return (-1);
+
+ if ((rc = umad_get_port(ca_name, ca_port, &port)) < 0)
+ return rc;
+
+ if (portid) {
+ memset(portid, 0, sizeof(*portid));
+ portid->lid = port.base_lid;
+ portid->sl = port.sm_sl;
+ }
+ if (portnum)
+ *portnum = port.portnum;
+ if (gid) {
+ memset(gid, 0, sizeof(*gid));
+ prefix = cl_ntoh64(port.gid_prefix);
+ guid = cl_ntoh64(port.port_guid);
+ mad_encode_field(*gid, IB_GID_PREFIX_F, &prefix);
+ mad_encode_field(*gid, IB_GID_GUID_F, &guid);
+ }
+
+ umad_release_port(&port);
+
+ return 0;
+}
+
+int resolve_gid(char *ca_name, uint8_t ca_port, ib_portid_t * portid,
+ ibmad_gid_t gid, ib_portid_t * sm_id,
+ const struct ibmad_port *srcport)
+{
+ ib_portid_t sm_portid;
+ char buf[IB_SA_DATA_SIZE] = { 0 };
+
+ if (!sm_id) {
+ sm_id = &sm_portid;
+ if (resolve_sm_portid(ca_name, ca_port, sm_id) < 0)
+ return -1;
+ }
+
+ if ((portid->lid =
+ ib_path_query_via(srcport, gid, gid, sm_id, buf)) < 0)
+ return -1;
+
+ return 0;
+}
+
+int resolve_guid(char *ca_name, uint8_t ca_port, ib_portid_t *portid,
+ uint64_t *guid, ib_portid_t *sm_id,
+ const struct ibmad_port *srcport)
+{
+ ib_portid_t sm_portid;
+ uint8_t buf[IB_SA_DATA_SIZE] = { 0 };
+ uint64_t prefix;
+ ibmad_gid_t selfgid;
+
+ if (!sm_id) {
+ sm_id = &sm_portid;
+ if (resolve_sm_portid(ca_name, ca_port, sm_id) < 0)
+ return -1;
+ }
+
+ if (resolve_self(ca_name, ca_port, NULL, NULL, &selfgid) < 0)
+ return -1;
+
+ memcpy(&prefix, portid->gid, sizeof(prefix));
+ if (!prefix)
+ mad_set_field64(portid->gid, 0, IB_GID_PREFIX_F,
+ IB_DEFAULT_SUBN_PREFIX);
+ if (guid)
+ mad_set_field64(portid->gid, 0, IB_GID_GUID_F, *guid);
+
+ if ((portid->lid =
+ ib_path_query_via(srcport, selfgid, portid->gid, sm_id, buf)) < 0)
+ return -1;
+
+ mad_decode_field(buf, IB_SA_PR_SL_F, &portid->sl);
+ return 0;
+}
+
+/*
+ * Callers of this function should ensure their ibmad_port has been opened with
+ * IB_SA_CLASS as this function may require the SA to resolve addresses.
+ */
+int resolve_portid_str(char *ca_name, uint8_t ca_port, ib_portid_t * portid,
+ char *addr_str, enum MAD_DEST dest_type,
+ ib_portid_t *sm_id, const struct ibmad_port *srcport)
+{
+ ibmad_gid_t gid;
+ uint64_t guid;
+ int lid;
+ char *routepath;
+ ib_portid_t selfportid = { 0 };
+ int selfport = 0;
+
+ memset(portid, 0, sizeof *portid);
+
+ switch (dest_type) {
+ case IB_DEST_LID:
+ lid = strtol(addr_str, 0, 0);
+ if (!IB_LID_VALID(lid))
+ return -1;
+ return ib_portid_set(portid, lid, 0, 0);
+
+ case IB_DEST_DRPATH:
+ if (str2drpath(&portid->drpath, addr_str, 0, 0) < 0)
+ return -1;
+ return 0;
+
+ case IB_DEST_GUID:
+ if (!(guid = strtoull(addr_str, 0, 0)))
+ return -1;
+
+ /* keep guid in portid? */
+ return resolve_guid(ca_name, ca_port, portid, &guid, sm_id,
+ srcport);
+
+ case IB_DEST_DRSLID:
+ lid = strtol(addr_str, &routepath, 0);
+ routepath++;
+ if (!IB_LID_VALID(lid))
+ return -1;
+ ib_portid_set(portid, lid, 0, 0);
+
+ /* handle DR parsing and set DrSLID to local lid */
+ if (resolve_self(ca_name, ca_port, &selfportid, &selfport,
+ NULL) < 0)
+ return -1;
+ if (str2drpath(&portid->drpath, routepath, selfportid.lid, 0) <
+ 0)
+ return -1;
+ return 0;
+
+ case IB_DEST_GID:
+ if (inet_pton(AF_INET6, addr_str, &gid) <= 0)
+ return -1;
+ return resolve_gid(ca_name, ca_port, portid, gid, sm_id,
+ srcport);
+ default:
+ IBWARN("bad dest_type %d", dest_type);
+ }
+
+ return -1;
+}
+
+static unsigned int get_max_width(unsigned int num)
+{
+ unsigned r = 0; /* 1x */
+
+ if (num & 8)
+ r = 3; /* 12x */
+ else {
+ if (num & 4)
+ r = 2; /* 8x */
+ else if (num & 2)
+ r = 1; /* 4x */
+ else if (num & 0x10)
+ r = 4; /* 2x */
+ }
+
+ return (1 << r);
+}
+
+static unsigned int get_max(unsigned int num)
+{
+ unsigned r = 0; // r will be lg(num)
+
+ while (num >>= 1) // unroll for more speed...
+ r++;
+
+ return (1 << r);
+}
+
+void get_max_msg(char *width_msg, char *speed_msg, int msg_size, ibnd_port_t * port)
+{
+ char buf[64];
+ uint32_t max_speed = 0;
+ uint32_t cap_mask, rem_cap_mask, fdr10;
+ uint8_t *info = NULL;
+
+ uint32_t max_width = get_max_width(mad_get_field(port->info, 0,
+ IB_PORT_LINK_WIDTH_SUPPORTED_F)
+ & mad_get_field(port->remoteport->info, 0,
+ IB_PORT_LINK_WIDTH_SUPPORTED_F));
+ if ((max_width & mad_get_field(port->info, 0,
+ IB_PORT_LINK_WIDTH_ACTIVE_F)) == 0)
+ // we are not at the max supported width
+ // print what we could be at.
+ snprintf(width_msg, msg_size, "Could be %s",
+ mad_dump_val(IB_PORT_LINK_WIDTH_ACTIVE_F,
+ buf, 64, &max_width));
+
+ if (port->node->type == IB_NODE_SWITCH) {
+ if (port->node->ports[0])
+ info = (uint8_t *)&port->node->ports[0]->info;
+ }
+ else
+ info = (uint8_t *)&port->info;
+
+ if (info)
+ cap_mask = mad_get_field(info, 0, IB_PORT_CAPMASK_F);
+ else
+ cap_mask = 0;
+
+ info = NULL;
+ if (port->remoteport->node->type == IB_NODE_SWITCH) {
+ if (port->remoteport->node->ports[0])
+ info = (uint8_t *)&port->remoteport->node->ports[0]->info;
+ } else
+ info = (uint8_t *)&port->remoteport->info;
+
+ if (info)
+ rem_cap_mask = mad_get_field(info, 0, IB_PORT_CAPMASK_F);
+ else
+ rem_cap_mask = 0;
+ if (cap_mask & CL_NTOH32(IB_PORT_CAP_HAS_EXT_SPEEDS) &&
+ rem_cap_mask & CL_NTOH32(IB_PORT_CAP_HAS_EXT_SPEEDS))
+ goto check_ext_speed;
+check_fdr10_supp:
+ fdr10 = (mad_get_field(port->ext_info, 0,
+ IB_MLNX_EXT_PORT_LINK_SPEED_SUPPORTED_F) & FDR10)
+ && (mad_get_field(port->remoteport->ext_info, 0,
+ IB_MLNX_EXT_PORT_LINK_SPEED_SUPPORTED_F) & FDR10);
+ if (fdr10)
+ goto check_fdr10_active;
+
+ max_speed = get_max(mad_get_field(port->info, 0,
+ IB_PORT_LINK_SPEED_SUPPORTED_F)
+ & mad_get_field(port->remoteport->info, 0,
+ IB_PORT_LINK_SPEED_SUPPORTED_F));
+ if ((max_speed & mad_get_field(port->info, 0,
+ IB_PORT_LINK_SPEED_ACTIVE_F)) == 0)
+ // we are not at the max supported speed
+ // print what we could be at.
+ snprintf(speed_msg, msg_size, "Could be %s",
+ mad_dump_val(IB_PORT_LINK_SPEED_ACTIVE_F,
+ buf, 64, &max_speed));
+ return;
+
+check_ext_speed:
+ if (mad_get_field(port->info, 0,
+ IB_PORT_LINK_SPEED_EXT_SUPPORTED_F) == 0 ||
+ mad_get_field(port->remoteport->info, 0,
+ IB_PORT_LINK_SPEED_EXT_SUPPORTED_F) == 0)
+ goto check_fdr10_supp;
+ max_speed = get_max(mad_get_field(port->info, 0,
+ IB_PORT_LINK_SPEED_EXT_SUPPORTED_F)
+ & mad_get_field(port->remoteport->info, 0,
+ IB_PORT_LINK_SPEED_EXT_SUPPORTED_F));
+ if ((max_speed & mad_get_field(port->info, 0,
+ IB_PORT_LINK_SPEED_EXT_ACTIVE_F)) == 0)
+ // we are not at the max supported extended speed
+ // print what we could be at.
+ snprintf(speed_msg, msg_size, "Could be %s",
+ mad_dump_val(IB_PORT_LINK_SPEED_EXT_ACTIVE_F,
+ buf, 64, &max_speed));
+ return;
+
+check_fdr10_active:
+ if ((mad_get_field(port->ext_info, 0,
+ IB_MLNX_EXT_PORT_LINK_SPEED_ACTIVE_F) & FDR10) == 0) {
+ /* Special case QDR to try to avoid confusion with FDR10 */
+ if (mad_get_field(port->info, 0, IB_PORT_LINK_SPEED_ACTIVE_F) == 4) /* QDR (10.0 Gbps) */
+ snprintf(speed_msg, msg_size,
+ "Could be FDR10 (Found link at QDR but expected speed is FDR10)");
+ else
+ snprintf(speed_msg, msg_size, "Could be FDR10");
+ }
+}
+
+int vsnprint_field(char *buf, size_t n, enum MAD_FIELDS f, int spacing,
+ const char *format, va_list va_args)
+{
+ int len, i, ret;
+
+ len = strlen(mad_field_name(f));
+ if (len + 2 > n || spacing + 1 > n)
+ return 0;
+
+ strncpy(buf, mad_field_name(f), n);
+ buf[len] = ':';
+ for (i = len+1; i < spacing+1; i++) {
+ buf[i] = '.';
+ }
+
+ ret = vsnprintf(&buf[spacing+1], n - spacing, format, va_args);
+ if (ret >= n - spacing)
+ buf[n] = '\0';
+
+ return ret + spacing;
+}
+
+int snprint_field(char *buf, size_t n, enum MAD_FIELDS f, int spacing,
+ const char *format, ...)
+{
+ va_list val;
+ int ret;
+
+ va_start(val, format);
+ ret = vsnprint_field(buf, n, f, spacing, format, val);
+ va_end(val);
+
+ return ret;
+}
+
+void dump_portinfo(void *pi, int tabs)
+{
+ int field, i;
+ char val[64];
+ char buf[1024];
+
+ for (field = IB_PORT_FIRST_F; field < IB_PORT_LAST_F; field++) {
+ for (i=0;i<tabs;i++)
+ printf("\t");
+ if (field == IB_PORT_MKEY_F && show_keys == 0) {
+ snprint_field(buf, 1024, field, 32, NOT_DISPLAYED_STR);
+ } else {
+ mad_decode_field(pi, field, val);
+ if (!mad_dump_field(field, buf, 1024, val))
+ return;
+ }
+ printf("%s\n", buf);
+ }
+
+ for (field = IB_PORT_CAPMASK2_F;
+ field < IB_PORT_LINK_SPEED_EXT_LAST_F; field++) {
+ for (i=0;i<tabs;i++)
+ printf("\t");
+ mad_decode_field(pi, field, val);
+ if (!mad_dump_field(field, buf, 1024, val))
+ return;
+ printf("%s\n", buf);
+ }
+}
+
+op_fn_t *match_op(const match_rec_t match_tbl[], char *name)
+{
+ const match_rec_t *r;
+ for (r = match_tbl; r->name; r++)
+ if (!strcasecmp(r->name, name) ||
+ (r->alias && !strcasecmp(r->alias, name)))
+ return r->fn;
+ return NULL;
+}
diff --git a/contrib/ofed/infiniband-diags/src/ibdiag_common.h b/contrib/ofed/infiniband-diags/src/ibdiag_common.h
new file mode 100644
index 000000000000..08bbf6be965e
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/src/ibdiag_common.h
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2006-2007 The Regents of the University of California.
+ * Copyright (c) 2004-2009 Voltaire Inc. All rights reserved.
+ * Copyright (c) 2002-2010 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ * Copyright (c) 2009 HNR Consulting. All rights reserved.
+ * Copyright (c) 2011 Lawrence Livermore National Security. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _IBDIAG_COMMON_H_
+#define _IBDIAG_COMMON_H_
+
+#include <stdarg.h>
+#include <infiniband/mad.h>
+#include <infiniband/iba/ib_types.h>
+#include <infiniband/ibnetdisc.h>
+
+extern int ibverbose;
+extern char *ibd_ca;
+extern int ibd_ca_port;
+extern enum MAD_DEST ibd_dest_type;
+extern ib_portid_t *ibd_sm_id;
+extern int ibd_timeout;
+extern uint32_t ibd_ibnetdisc_flags;
+extern uint64_t ibd_mkey;
+extern uint64_t ibd_sakey;
+extern int show_keys;
+extern char *ibd_nd_format;
+
+/*========================================================*/
+/* External interface */
+/*========================================================*/
+
+#undef DEBUG
+#define DEBUG(fmt, ...) do { \
+ if (ibdebug) IBDEBUG(fmt, ## __VA_ARGS__); \
+} while (0)
+#define VERBOSE(fmt, ...) do { \
+ if (ibverbose) IBVERBOSE(fmt, ## __VA_ARGS__); \
+} while (0)
+#define IBEXIT(fmt, ...) ibexit(__FUNCTION__, fmt, ## __VA_ARGS__)
+
+#define NOT_DISPLAYED_STR "<not displayed>"
+
+/* not all versions of ib_types.h will have this define */
+#ifndef IB_PM_PC_XMIT_WAIT_SUP
+#define IB_PM_PC_XMIT_WAIT_SUP (CL_HTON16(((uint16_t)1)<<12))
+#endif
+
+/* PM ClassPortInfo CapabilityMask Bits */
+#ifndef IS_PM_RSFEC_COUNTERS_SUP
+#define IS_PM_RSFEC_COUNTERS_SUP (CL_HTON16(((uint16_t)1)<<14))
+#endif
+
+#ifndef IB_PM_IS_QP1_DROP_SUP
+#define IB_PM_IS_QP1_DROP_SUP (CL_HTON16(((uint16_t)1)<<15))
+#endif
+
+/* PM ClassPortInfo CapabilityMask2 Bits */
+#ifndef IB_PM_IS_ADDL_PORT_CTRS_EXT_SUP
+#define IB_PM_IS_ADDL_PORT_CTRS_EXT_SUP (CL_HTON32(((uint32_t)1)<<1))
+#endif
+
+/* SM PortInfo CapabilityMask2 Bits */
+#ifndef IB_PORT_CAP2_IS_PORT_INFO_EXT_SUPPORTED
+#define IB_PORT_CAP2_IS_PORT_INFO_EXT_SUPPORTED (CL_HTON16(0x0002))
+#endif
+
+/* SM PortInfoExtended Fec Mode Bits */
+#ifndef IB_PORT_EXT_NO_FEC_MODE_ACTIVE
+#define IB_PORT_EXT_NO_FEC_MODE_ACTIVE 0
+#endif
+
+#ifndef IB_PORT_EXT_FIRE_CODE_FEC_MODE_ACTIVE
+#define IB_PORT_EXT_FIRE_CODE_FEC_MODE_ACTIVE (CL_HTON16(0x0001))
+#endif
+
+#ifndef IB_PORT_EXT_RS_FEC_MODE_ACTIVE
+#define IB_PORT_EXT_RS_FEC_MODE_ACTIVE (CL_HTON16(0x0002))
+#endif
+
+#ifndef IB_PORT_EXT_LOW_LATENCY_RS_FEC_MODE_ACTIVE
+#define IB_PORT_EXT_LOW_LATENCY_RS_FEC_MODE_ACTIVE (CL_HTON16(0x0003))
+#endif
+
+/* SM PortInfoExtended CapabilityMask Bits */
+#ifndef IB_PORT_EXT_CAP_IS_FEC_MODE_SUPPORTED
+#define IB_PORT_EXT_CAP_IS_FEC_MODE_SUPPORTED (CL_HTON32(0x00000001))
+#endif
+
+struct ibdiag_opt {
+ const char *name;
+ char letter;
+ unsigned has_arg;
+ const char *arg_tmpl;
+ const char *description;
+};
+
+extern int ibdiag_process_opts(int argc, char *const argv[], void *context,
+ const char *exclude_common_str,
+ const struct ibdiag_opt custom_opts[],
+ int (*custom_handler) (void *cxt, int val,
+ char *optarg),
+ const char *usage_args,
+ const char *usage_examples[]);
+extern void ibdiag_show_usage();
+extern void ibexit(const char *fn, char *msg, ...);
+
+/* convert counter values to a float with a unit specifier returned (using
+ * binary prefix)
+ * "data" is a flag indicating this counter is a byte counter multiplied by 4
+ * as per PortCounters[Extended]
+ */
+extern char *conv_cnt_human_readable(uint64_t val64, float *val, int data);
+
+int is_mlnx_ext_port_info_supported(uint32_t vendorid, uint16_t devid);
+
+int is_port_info_extended_supported(ib_portid_t * dest, int port,
+ struct ibmad_port *srcport);
+void get_max_msg(char *width_msg, char *speed_msg, int msg_size,
+ ibnd_port_t * port);
+
+int resolve_sm_portid(char *ca_name, uint8_t portnum, ib_portid_t *sm_id);
+int resolve_self(char *ca_name, uint8_t ca_port, ib_portid_t *portid,
+ int *port, ibmad_gid_t *gid);
+int resolve_portid_str(char *ca_name, uint8_t ca_port, ib_portid_t * portid,
+ char *addr_str, enum MAD_DEST dest_type,
+ ib_portid_t *sm_id, const struct ibmad_port *srcport);
+int vsnprint_field(char *buf, size_t n, enum MAD_FIELDS f, int spacing,
+ const char *format, va_list va_args);
+int snprint_field(char *buf, size_t n, enum MAD_FIELDS f, int spacing,
+ const char *format, ...);
+void dump_portinfo(void *pi, int tabs);
+
+/**
+ * Some common command line parsing
+ */
+typedef char *(op_fn_t) (ib_portid_t * dest, char **argv, int argc);
+
+typedef struct match_rec {
+ const char *name, *alias;
+ op_fn_t *fn;
+ unsigned opt_portnum;
+ char *ops_extra;
+} match_rec_t;
+
+op_fn_t *match_op(const match_rec_t match_tbl[], char *name);
+
+#endif /* _IBDIAG_COMMON_H_ */
diff --git a/contrib/ofed/infiniband-diags/src/ibdiag_sa.c b/contrib/ofed/infiniband-diags/src/ibdiag_sa.c
new file mode 100644
index 000000000000..ea272a976d75
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/src/ibdiag_sa.c
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2006-2007 The Regents of the University of California.
+ * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2010 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ * Copyright (c) 2009 HNR Consulting. All rights reserved.
+ * Copyright (c) 2011 Lawrence Livermore National Security. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+
+#include <errno.h>
+#include <infiniband/umad.h>
+
+#include "ibdiag_common.h"
+#include "ibdiag_sa.h"
+
+/* define a common SA query structure
+ * This is by no means optimal but it moves the saquery functionality out of
+ * the saquery tool and provides it to other utilities.
+ */
+
+struct sa_handle * sa_get_handle(void)
+{
+ struct sa_handle * handle;
+ handle = calloc(1, sizeof(*handle));
+ if (!handle)
+ IBPANIC("calloc failed");
+
+ resolve_sm_portid(ibd_ca, ibd_ca_port, &handle->dport);
+ if (!handle->dport.lid) {
+ IBWARN("No SM/SA found on port %s:%d",
+ ibd_ca ? "" : ibd_ca,
+ ibd_ca_port);
+ free(handle);
+ return (NULL);
+ }
+
+ handle->dport.qp = 1;
+ if (!handle->dport.qkey)
+ handle->dport.qkey = IB_DEFAULT_QP1_QKEY;
+
+ handle->fd = umad_open_port(ibd_ca, ibd_ca_port);
+ handle->agent = umad_register(handle->fd, IB_SA_CLASS, 2, 1, NULL);
+
+ return handle;
+}
+
+int sa_set_handle(struct sa_handle * handle, int grh_present, ibmad_gid_t *gid)
+{
+ if (grh_present) {
+ if (gid == NULL) {
+ return -1;
+ } else {
+ handle->dport.grh_present = 1;
+ memcpy(handle->dport.gid, gid, 16);
+ }
+ }
+ return 0;
+}
+
+void sa_free_handle(struct sa_handle * h)
+{
+ umad_unregister(h->fd, h->agent);
+ umad_close_port(h->fd);
+ free(h);
+}
+
+int sa_query(struct sa_handle * h, uint8_t method,
+ uint16_t attr, uint32_t mod, uint64_t comp_mask,
+ uint64_t sm_key, void *data, size_t datasz,
+ struct sa_query_result *result)
+{
+ ib_rpc_t rpc;
+ void *umad, *mad;
+ int ret, offset, len = 256;
+
+ memset(&rpc, 0, sizeof(rpc));
+ rpc.mgtclass = IB_SA_CLASS;
+ rpc.method = method;
+ rpc.attr.id = attr;
+ rpc.attr.mod = mod;
+ rpc.mask = comp_mask;
+ rpc.datasz = datasz;
+ rpc.dataoffs = IB_SA_DATA_OFFS;
+
+ umad = calloc(1, len + umad_size());
+ if (!umad)
+ IBPANIC("cannot alloc mem for umad: %s\n", strerror(errno));
+
+ mad_build_pkt(umad, &rpc, &h->dport, NULL, data);
+
+ mad_set_field64(umad_get_mad(umad), 0, IB_SA_MKEY_F, sm_key);
+
+ if (ibdebug > 1)
+ xdump(stdout, "SA Request:\n", umad_get_mad(umad), len);
+
+ if (h->dport.grh_present) {
+ ib_mad_addr_t *p_mad_addr = umad_get_mad_addr(umad);
+ p_mad_addr->grh_present = 1;
+ p_mad_addr->gid_index = 0;
+ p_mad_addr->hop_limit = 0;
+ p_mad_addr->traffic_class = 0;
+ memcpy(p_mad_addr->gid, h->dport.gid, 16);
+ }
+
+ ret = umad_send(h->fd, h->agent, umad, len, ibd_timeout, 0);
+ if (ret < 0) {
+ IBWARN("umad_send failed: attr 0x%x: %s\n",
+ attr, strerror(errno));
+ free(umad);
+ return (-ret);
+ }
+
+recv_mad:
+ ret = umad_recv(h->fd, umad, &len, ibd_timeout);
+ if (ret < 0) {
+ if (errno == ENOSPC) {
+ umad = realloc(umad, umad_size() + len);
+ goto recv_mad;
+ }
+ IBWARN("umad_recv failed: attr 0x%x: %s\n", attr,
+ strerror(errno));
+ free(umad);
+ return (-ret);
+ }
+
+ if ((ret = umad_status(umad)))
+ return ret;
+
+ mad = umad_get_mad(umad);
+
+ if (ibdebug > 1)
+ xdump(stdout, "SA Response:\n", mad, len);
+
+ method = (uint8_t) mad_get_field(mad, 0, IB_MAD_METHOD_F);
+ offset = mad_get_field(mad, 0, IB_SA_ATTROFFS_F);
+ result->status = mad_get_field(mad, 0, IB_MAD_STATUS_F);
+ result->p_result_madw = mad;
+ if (result->status != IB_SA_MAD_STATUS_SUCCESS)
+ result->result_cnt = 0;
+ else if (method != IB_MAD_METHOD_GET_TABLE)
+ result->result_cnt = 1;
+ else if (!offset)
+ result->result_cnt = 0;
+ else
+ result->result_cnt = (len - IB_SA_DATA_OFFS) / (offset << 3);
+
+ return 0;
+}
+
+void sa_free_result_mad(struct sa_query_result *result)
+{
+ if (result->p_result_madw) {
+ free((uint8_t *) result->p_result_madw - umad_size());
+ result->p_result_madw = NULL;
+ }
+}
+
+void *sa_get_query_rec(void *mad, unsigned i)
+{
+ int offset = mad_get_field(mad, 0, IB_SA_ATTROFFS_F);
+ return (uint8_t *) mad + IB_SA_DATA_OFFS + i * (offset << 3);
+}
+
+static const char *ib_sa_error_str[] = {
+ "SA_NO_ERROR",
+ "SA_ERR_NO_RESOURCES",
+ "SA_ERR_REQ_INVALID",
+ "SA_ERR_NO_RECORDS",
+ "SA_ERR_TOO_MANY_RECORDS",
+ "SA_ERR_REQ_INVALID_GID",
+ "SA_ERR_REQ_INSUFFICIENT_COMPONENTS",
+ "SA_ERR_REQ_DENIED",
+ "SA_ERR_STATUS_PRIO_SUGGESTED",
+ "SA_ERR_UNKNOWN"
+};
+
+#define ARR_SIZE(a) (sizeof(a)/sizeof((a)[0]))
+#define SA_ERR_UNKNOWN (ARR_SIZE(ib_sa_error_str) - 1)
+
+static inline const char *ib_sa_err_str(IN uint8_t status)
+{
+ if (status > SA_ERR_UNKNOWN)
+ status = SA_ERR_UNKNOWN;
+ return (ib_sa_error_str[status]);
+}
+
+static const char *ib_mad_inv_field_str[] = {
+ "MAD No invalid fields",
+ "MAD Bad version",
+ "MAD Method specified is not supported",
+ "MAD Method/Attribute combination is not supported",
+ "MAD Reserved",
+ "MAD Reserved",
+ "MAD Reserved",
+ "MAD Invalid value in Attribute field(s) or Attribute Modifier"
+ "MAD UNKNOWN ERROR"
+};
+#define MAD_ERR_UNKNOWN (ARR_SIZE(ib_mad_inv_field_str) - 1)
+
+static inline const char *ib_mad_inv_field_err_str(IN uint8_t f)
+{
+ if (f > MAD_ERR_UNKNOWN)
+ f = MAD_ERR_UNKNOWN;
+ return (ib_mad_inv_field_str[f]);
+}
+
+void sa_report_err(int status)
+{
+ int st = status & 0xff;
+ char mad_err_str[64] = { 0 };
+ char sa_err_str[64] = { 0 };
+
+ if (st)
+ sprintf(mad_err_str, " (%s; %s; %s)",
+ (st & 0x1) ? "BUSY" : "",
+ (st & 0x2) ? "Redirection Required" : "",
+ ib_mad_inv_field_err_str(st>>2));
+
+
+ st = status >> 8;
+ if (st)
+ sprintf(sa_err_str, " SA(%s)", ib_sa_err_str((uint8_t) st));
+
+ fprintf(stderr, "ERROR: Query result returned 0x%04x, %s%s\n",
+ status, mad_err_str, sa_err_str);
+}
diff --git a/contrib/ofed/infiniband-diags/src/ibdiag_sa.h b/contrib/ofed/infiniband-diags/src/ibdiag_sa.h
new file mode 100644
index 000000000000..537fcfe724b8
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/src/ibdiag_sa.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2006-2007 The Regents of the University of California.
+ * Copyright (c) 2004-2009 Voltaire Inc. All rights reserved.
+ * Copyright (c) 2002-2010 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2003 Intel Corporation. All rights reserved.
+ * Copyright (c) 2009 HNR Consulting. All rights reserved.
+ * Copyright (c) 2012 Lawrence Livermore National Security. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _IBDIAG_SA_H_
+#define _IBDIAG_SA_H_
+
+#include <infiniband/mad.h>
+#include <infiniband/iba/ib_types.h>
+
+/* define an SA query structure to be common
+ * This is by no means optimal but it moves the saquery functionality out of
+ * the saquery tool and provides it to other utilities.
+ */
+struct sa_handle {
+ int fd, agent;
+ ib_portid_t dport;
+ struct ibmad_port *srcport;
+};
+
+struct sa_query_result {
+ uint32_t status;
+ unsigned result_cnt;
+ void *p_result_madw;
+};
+
+/* NOTE: umad_init must be called prior to sa_get_handle */
+struct sa_handle * sa_get_handle(void);
+int sa_set_handle(struct sa_handle * handle, int grh_present, ibmad_gid_t *gid);
+void sa_free_handle(struct sa_handle * h);
+
+int sa_query(struct sa_handle *h, uint8_t method,
+ uint16_t attr, uint32_t mod, uint64_t comp_mask, uint64_t sm_key,
+ void *data, size_t datasz, struct sa_query_result *result);
+void sa_free_result_mad(struct sa_query_result *result);
+void *sa_get_query_rec(void *mad, unsigned i);
+void sa_report_err(int status);
+
+/* Macros for setting query values and ComponentMasks */
+#define cl_hton8(x) (x)
+#define CHECK_AND_SET_VAL(val, size, comp_with, target, name, mask) \
+ if ((int##size##_t) val != (int##size##_t) comp_with) { \
+ target = cl_hton##size((uint##size##_t) val); \
+ comp_mask |= IB_##name##_COMPMASK_##mask; \
+ }
+
+#define CHECK_AND_SET_GID(val, target, name, mask) \
+ if (valid_gid(&(val))) { \
+ memcpy(&(target), &(val), sizeof(val)); \
+ comp_mask |= IB_##name##_COMPMASK_##mask; \
+ }
+
+#define CHECK_AND_SET_VAL_AND_SEL(val, target, name, mask, sel) \
+ if (val) { \
+ target = val; \
+ comp_mask |= IB_##name##_COMPMASK_##mask##sel; \
+ comp_mask |= IB_##name##_COMPMASK_##mask; \
+ }
+
+#endif /* _IBDIAG_SA_H_ */
diff --git a/contrib/ofed/infiniband-diags/src/ibdiag_version.h b/contrib/ofed/infiniband-diags/src/ibdiag_version.h
new file mode 100644
index 000000000000..142d71881b2b
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/src/ibdiag_version.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2008 Voltaire Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#ifndef _IBDIAG_VERSION_H_
+#define _IBDIAG_VERSION_H_
+
+#define IBDIAG_VERSION "1.6.7"
+
+#endif /* _IBDIAG_VERSION_H_ */
diff --git a/contrib/ofed/infiniband-diags/src/iblinkinfo.c b/contrib/ofed/infiniband-diags/src/iblinkinfo.c
new file mode 100644
index 000000000000..40e012d44769
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/src/iblinkinfo.c
@@ -0,0 +1,768 @@
+/*
+ * Copyright (c) 2004-2009 Voltaire Inc. All rights reserved.
+ * Copyright (c) 2007 Xsigo Systems Inc. All rights reserved.
+ * Copyright (c) 2008 Lawrence Livermore National Lab. All rights reserved.
+ * Copyright (c) 2010,2011 Mellanox Technologies LTD. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <time.h>
+#include <string.h>
+#include <getopt.h>
+#include <errno.h>
+#include <inttypes.h>
+
+#include <complib/cl_nodenamemap.h>
+#include <infiniband/ibnetdisc.h>
+
+#include "ibdiag_common.h"
+
+#define DIFF_FLAG_PORT_CONNECTION 0x01
+#define DIFF_FLAG_PORT_STATE 0x02
+#define DIFF_FLAG_LID 0x04
+#define DIFF_FLAG_NODE_DESCRIPTION 0x08
+
+#define DIFF_FLAG_DEFAULT (DIFF_FLAG_PORT_CONNECTION | DIFF_FLAG_PORT_STATE)
+
+static char *node_name_map_file = NULL;
+static nn_map_t *node_name_map = NULL;
+static char *load_cache_file = NULL;
+static char *diff_cache_file = NULL;
+static unsigned diffcheck_flags = DIFF_FLAG_DEFAULT;
+static char *filterdownports_cache_file = NULL;
+static ibnd_fabric_t *filterdownports_fabric = NULL;
+
+static uint64_t guid = 0;
+static char *guid_str = NULL;
+static char *dr_path = NULL;
+static int all = 0;
+
+static int down_links_only = 0;
+static int line_mode = 0;
+static int add_sw_settings = 0;
+static int only_flag = 0;
+static int only_type = 0;
+
+int filterdownport_check(ibnd_node_t * node, ibnd_port_t * port)
+{
+ ibnd_node_t *fsw;
+ ibnd_port_t *fport;
+ int fistate;
+
+ fsw = ibnd_find_node_guid(filterdownports_fabric, node->guid);
+
+ if (!fsw)
+ return 0;
+
+ if (port->portnum > fsw->numports)
+ return 0;
+
+ fport = fsw->ports[port->portnum];
+
+ if (!fport)
+ return 0;
+
+ fistate = mad_get_field(fport->info, 0, IB_PORT_STATE_F);
+
+ return (fistate == IB_LINK_DOWN) ? 1 : 0;
+}
+
+void print_port(ibnd_node_t * node, ibnd_port_t * port, char *out_prefix)
+{
+ char width[64], speed[64], state[64], physstate[64];
+ char remote_guid_str[256];
+ char remote_str[256];
+ char link_str[256];
+ char width_msg[256];
+ char speed_msg[256];
+ char ext_port_str[256];
+ int iwidth, ispeed, fdr10, espeed, istate, iphystate, cap_mask;
+ int n = 0;
+ uint8_t *info = NULL;
+
+ if (!port)
+ return;
+
+ iwidth = mad_get_field(port->info, 0, IB_PORT_LINK_WIDTH_ACTIVE_F);
+ ispeed = mad_get_field(port->info, 0, IB_PORT_LINK_SPEED_ACTIVE_F);
+ fdr10 = mad_get_field(port->ext_info, 0,
+ IB_MLNX_EXT_PORT_LINK_SPEED_ACTIVE_F) & FDR10;
+
+ if (port->node->type == IB_NODE_SWITCH) {
+ if (port->node->ports[0])
+ info = (uint8_t *)&port->node->ports[0]->info;
+ }
+ else
+ info = (uint8_t *)&port->info;
+
+ if (info) {
+ cap_mask = mad_get_field(info, 0, IB_PORT_CAPMASK_F);
+ if (cap_mask & CL_NTOH32(IB_PORT_CAP_HAS_EXT_SPEEDS))
+ espeed = mad_get_field(port->info, 0,
+ IB_PORT_LINK_SPEED_EXT_ACTIVE_F);
+ else
+ espeed = 0;
+ } else {
+ ispeed = 0;
+ iwidth = 0;
+ espeed = 0;
+ }
+
+ istate = mad_get_field(port->info, 0, IB_PORT_STATE_F);
+ iphystate = mad_get_field(port->info, 0, IB_PORT_PHYS_STATE_F);
+
+ remote_guid_str[0] = '\0';
+ remote_str[0] = '\0';
+ link_str[0] = '\0';
+ width_msg[0] = '\0';
+ speed_msg[0] = '\0';
+
+ if (istate == IB_LINK_DOWN
+ && filterdownports_fabric
+ && filterdownport_check(node, port))
+ return;
+
+ /* C14-24.2.1 states that a down port allows for invalid data to be
+ * returned for all PortInfo components except PortState and
+ * PortPhysicalState */
+ if (istate != IB_LINK_DOWN) {
+ if (!espeed) {
+ if (fdr10)
+ sprintf(speed, "10.0 Gbps (FDR10)");
+ else
+ mad_dump_val(IB_PORT_LINK_SPEED_ACTIVE_F, speed,
+ 64, &ispeed);
+ } else
+ mad_dump_val(IB_PORT_LINK_SPEED_EXT_ACTIVE_F, speed,
+ 64, &espeed);
+
+ n = snprintf(link_str, 256, "(%3s %18s %6s/%8s)",
+ mad_dump_val(IB_PORT_LINK_WIDTH_ACTIVE_F, width, 64,
+ &iwidth),
+ speed,
+ mad_dump_val(IB_PORT_STATE_F, state, 64, &istate),
+ mad_dump_val(IB_PORT_PHYS_STATE_F, physstate, 64,
+ &iphystate));
+ } else {
+ n = snprintf(link_str, 256, "( %6s/%8s)",
+ mad_dump_val(IB_PORT_STATE_F, state, 64, &istate),
+ mad_dump_val(IB_PORT_PHYS_STATE_F, physstate, 64,
+ &iphystate));
+ }
+
+ /* again default values due to C14-24.2.1 */
+ if (add_sw_settings && istate != IB_LINK_DOWN) {
+ snprintf(link_str + n, 256 - n,
+ " (HOQ:%d VL_Stall:%d)",
+ mad_get_field(port->info, 0,
+ IB_PORT_HOQ_LIFE_F),
+ mad_get_field(port->info, 0,
+ IB_PORT_VL_STALL_COUNT_F));
+ }
+
+ if (port->remoteport) {
+ char *remap =
+ remap_node_name(node_name_map, port->remoteport->node->guid,
+ port->remoteport->node->nodedesc);
+
+ if (port->remoteport->ext_portnum)
+ snprintf(ext_port_str, 256, "%d",
+ port->remoteport->ext_portnum);
+ else
+ ext_port_str[0] = '\0';
+
+ get_max_msg(width_msg, speed_msg, 256, port);
+
+ if (line_mode) {
+ snprintf(remote_guid_str, 256,
+ "0x%016" PRIx64 " ",
+ port->remoteport->guid);
+ }
+
+ snprintf(remote_str, 256, "%s%6d %4d[%2s] \"%s\" (%s %s)\n",
+ remote_guid_str, port->remoteport->base_lid ?
+ port->remoteport->base_lid :
+ port->remoteport->node->smalid,
+ port->remoteport->portnum, ext_port_str, remap,
+ width_msg, speed_msg);
+ free(remap);
+ } else {
+ if (istate == IB_LINK_DOWN)
+ snprintf(remote_str, 256, " [ ] \"\" ( )\n");
+ else
+ snprintf(remote_str, 256, " \"Port not available\"\n");
+ }
+
+ if (port->ext_portnum)
+ snprintf(ext_port_str, 256, "%d", port->ext_portnum);
+ else
+ ext_port_str[0] = '\0';
+
+ if (line_mode) {
+ char *remap = remap_node_name(node_name_map, node->guid,
+ node->nodedesc);
+ printf("%s0x%016" PRIx64 " \"%30s\" ",
+ out_prefix ? out_prefix : "",
+ port->guid, remap);
+ free(remap);
+ } else
+ printf("%s ", out_prefix ? out_prefix : "");
+
+ if (port->node->type != IB_NODE_SWITCH) {
+ if (!line_mode)
+ printf("0x%016" PRIx64 " ", port->guid);
+
+ printf("%6d %4d[%2s] ==%s==> %s",
+ port->base_lid,
+ port->portnum, ext_port_str, link_str, remote_str);
+ } else
+ printf("%6d %4d[%2s] ==%s==> %s",
+ node->smalid, port->portnum, ext_port_str,
+ link_str, remote_str);
+}
+
+static inline const char *nodetype_str(ibnd_node_t * node)
+{
+ switch (node->type) {
+ case IB_NODE_SWITCH:
+ return "Switch";
+ case IB_NODE_CA:
+ return "CA";
+ case IB_NODE_ROUTER:
+ return "Router";
+ }
+ return "??";
+}
+
+void print_node_header(ibnd_node_t *node, int *out_header_flag,
+ char *out_prefix)
+{
+ uint64_t guid = 0;
+ if ((!out_header_flag || !(*out_header_flag)) && !line_mode) {
+ char *remap =
+ remap_node_name(node_name_map, node->guid, node->nodedesc);
+ if (node->type == IB_NODE_SWITCH) {
+ if (node->ports[0])
+ guid = node->ports[0]->guid;
+ else /* if (node->info) */
+ guid = mad_get_field64(node->info, 0, IB_NODE_PORT_GUID_F);
+
+ printf("%s%s: 0x%016" PRIx64 " %s:\n",
+ out_prefix ? out_prefix : "",
+ nodetype_str(node),
+ guid,
+ remap);
+ } else
+ printf("%s%s: %s:\n",
+ out_prefix ? out_prefix : "",
+ nodetype_str(node), remap);
+ (*out_header_flag)++;
+ free(remap);
+ }
+}
+
+void print_node(ibnd_node_t * node, void *user_data)
+{
+ int i = 0;
+ int head_print = 0;
+ char *out_prefix = (char *)user_data;
+
+ for (i = 1; i <= node->numports; i++) {
+ ibnd_port_t *port = node->ports[i];
+ if (!port)
+ continue;
+ if (!down_links_only ||
+ mad_get_field(port->info, 0,
+ IB_PORT_STATE_F) == IB_LINK_DOWN) {
+ print_node_header(node, &head_print, out_prefix);
+ print_port(node, port, out_prefix);
+ }
+ }
+}
+
+struct iter_diff_data {
+ uint32_t diff_flags;
+ ibnd_fabric_t *fabric1;
+ ibnd_fabric_t *fabric2;
+ char *fabric1_prefix;
+ char *fabric2_prefix;
+};
+
+void diff_node_ports(ibnd_node_t * fabric1_node, ibnd_node_t * fabric2_node,
+ int *head_print, struct iter_diff_data *data)
+{
+ int i = 0;
+
+ for (i = 1; i <= fabric1_node->numports; i++) {
+ ibnd_port_t *fabric1_port, *fabric2_port;
+ int output_diff = 0;
+
+ fabric1_port = fabric1_node->ports[i];
+ fabric2_port = fabric2_node->ports[i];
+
+ if (!fabric1_port && !fabric2_port)
+ continue;
+
+ if (data->diff_flags & DIFF_FLAG_PORT_CONNECTION) {
+ if ((fabric1_port && !fabric2_port)
+ || (!fabric1_port && fabric2_port)
+ || (fabric1_port->remoteport
+ && !fabric2_port->remoteport)
+ || (!fabric1_port->remoteport
+ && fabric2_port->remoteport)
+ || (fabric1_port->remoteport
+ && fabric2_port->remoteport
+ && fabric1_port->remoteport->guid !=
+ fabric2_port->remoteport->guid))
+ output_diff++;
+ }
+
+ /* if either fabric1_port or fabric2_port NULL, should be
+ * handled by port connection diff code
+ */
+ if (data->diff_flags & DIFF_FLAG_PORT_STATE
+ && fabric1_port
+ && fabric2_port) {
+ int state1, state2;
+
+ state1 = mad_get_field(fabric1_port->info, 0,
+ IB_PORT_STATE_F);
+ state2 = mad_get_field(fabric2_port->info, 0,
+ IB_PORT_STATE_F);
+
+ if (state1 != state2)
+ output_diff++;
+ }
+
+ if (data->diff_flags & DIFF_FLAG_PORT_CONNECTION
+ && data->diff_flags & DIFF_FLAG_LID
+ && fabric1_port && fabric2_port
+ && fabric1_port->remoteport && fabric2_port->remoteport
+ && fabric1_port->remoteport->base_lid != fabric2_port->remoteport->base_lid)
+ output_diff++;
+
+ if (data->diff_flags & DIFF_FLAG_PORT_CONNECTION
+ && data->diff_flags & DIFF_FLAG_NODE_DESCRIPTION
+ && fabric1_port && fabric2_port
+ && fabric1_port->remoteport && fabric2_port->remoteport
+ && memcmp(fabric1_port->remoteport->node->nodedesc,
+ fabric2_port->remoteport->node->nodedesc,
+ IB_SMP_DATA_SIZE))
+ output_diff++;
+
+ if (output_diff && fabric1_port) {
+ print_node_header(fabric1_node,
+ head_print,
+ NULL);
+ print_port(fabric1_node,
+ fabric1_port,
+ data->fabric1_prefix);
+ }
+
+ if (output_diff && fabric2_port) {
+ print_node_header(fabric1_node,
+ head_print,
+ NULL);
+ print_port(fabric2_node,
+ fabric2_port,
+ data->fabric2_prefix);
+ }
+ }
+}
+
+void diff_node_iter(ibnd_node_t * fabric1_node, void *iter_user_data)
+{
+ struct iter_diff_data *data = iter_user_data;
+ ibnd_node_t *fabric2_node;
+ int head_print = 0;
+
+ DEBUG("DEBUG: fabric1_node %p\n", fabric1_node);
+
+ fabric2_node = ibnd_find_node_guid(data->fabric2, fabric1_node->guid);
+ if (!fabric2_node)
+ print_node(fabric1_node, data->fabric1_prefix);
+ else if (data->diff_flags &
+ (DIFF_FLAG_PORT_CONNECTION | DIFF_FLAG_PORT_STATE
+ | DIFF_FLAG_LID | DIFF_FLAG_NODE_DESCRIPTION)) {
+
+ if ((fabric1_node->type == IB_NODE_SWITCH
+ && data->diff_flags & DIFF_FLAG_LID
+ && fabric1_node->smalid != fabric2_node->smalid) ||
+ (data->diff_flags & DIFF_FLAG_NODE_DESCRIPTION
+ && memcmp(fabric1_node->nodedesc, fabric2_node->nodedesc,
+ IB_SMP_DATA_SIZE))) {
+ print_node_header(fabric1_node,
+ NULL,
+ data->fabric1_prefix);
+ print_node_header(fabric2_node,
+ NULL,
+ data->fabric2_prefix);
+ head_print++;
+ }
+
+ if (fabric1_node->numports != fabric2_node->numports) {
+ print_node_header(fabric1_node,
+ &head_print,
+ NULL);
+ printf("%snumports = %d\n", data->fabric1_prefix,
+ fabric1_node->numports);
+ printf("%snumports = %d\n", data->fabric2_prefix,
+ fabric2_node->numports);
+ return;
+ }
+
+ diff_node_ports(fabric1_node, fabric2_node,
+ &head_print, data);
+ }
+}
+
+int diff_node(ibnd_node_t * node, ibnd_fabric_t * orig_fabric,
+ ibnd_fabric_t * new_fabric)
+{
+ struct iter_diff_data iter_diff_data;
+
+ iter_diff_data.diff_flags = diffcheck_flags;
+ iter_diff_data.fabric1 = orig_fabric;
+ iter_diff_data.fabric2 = new_fabric;
+ iter_diff_data.fabric1_prefix = "< ";
+ iter_diff_data.fabric2_prefix = "> ";
+ if (node)
+ diff_node_iter(node, &iter_diff_data);
+ else {
+ if (only_flag)
+ ibnd_iter_nodes_type(orig_fabric, diff_node_iter,
+ only_type, &iter_diff_data);
+ else
+ ibnd_iter_nodes(orig_fabric, diff_node_iter,
+ &iter_diff_data);
+ }
+
+ /* Do opposite diff to find existence of node types
+ * in new_fabric but not in orig_fabric.
+ *
+ * In this diff, we don't need to check port connections,
+ * port state, lids, or node descriptions since it has already
+ * been done (i.e. checks are only done when guid exists on both
+ * orig and new).
+ */
+ iter_diff_data.diff_flags = diffcheck_flags & ~DIFF_FLAG_PORT_CONNECTION;
+ iter_diff_data.diff_flags &= ~DIFF_FLAG_PORT_STATE;
+ iter_diff_data.diff_flags &= ~DIFF_FLAG_LID;
+ iter_diff_data.diff_flags &= ~DIFF_FLAG_NODE_DESCRIPTION;
+ iter_diff_data.fabric1 = new_fabric;
+ iter_diff_data.fabric2 = orig_fabric;
+ iter_diff_data.fabric1_prefix = "> ";
+ iter_diff_data.fabric2_prefix = "< ";
+ if (node)
+ diff_node_iter(node, &iter_diff_data);
+ else {
+ if (only_flag)
+ ibnd_iter_nodes_type(new_fabric, diff_node_iter,
+ only_type, &iter_diff_data);
+ else
+ ibnd_iter_nodes(new_fabric, diff_node_iter,
+ &iter_diff_data);
+ }
+
+ return 0;
+}
+
+static int process_opt(void *context, int ch, char *optarg)
+{
+ struct ibnd_config *cfg = context;
+ char *p;
+
+ switch (ch) {
+ case 1:
+ node_name_map_file = strdup(optarg);
+ break;
+ case 2:
+ load_cache_file = strdup(optarg);
+ break;
+ case 3:
+ diff_cache_file = strdup(optarg);
+ break;
+ case 4:
+ diffcheck_flags = 0;
+ p = strtok(optarg, ",");
+ while (p) {
+ if (!strcasecmp(p, "port"))
+ diffcheck_flags |= DIFF_FLAG_PORT_CONNECTION;
+ else if (!strcasecmp(p, "state"))
+ diffcheck_flags |= DIFF_FLAG_PORT_STATE;
+ else if (!strcasecmp(p, "lid"))
+ diffcheck_flags |= DIFF_FLAG_LID;
+ else if (!strcasecmp(p, "nodedesc"))
+ diffcheck_flags |= DIFF_FLAG_NODE_DESCRIPTION;
+ else {
+ fprintf(stderr, "invalid diff check key: %s\n",
+ p);
+ return -1;
+ }
+ p = strtok(NULL, ",");
+ }
+ break;
+ case 5:
+ filterdownports_cache_file = strdup(optarg);
+ break;
+ case 6:
+ only_flag = 1;
+ only_type = IB_NODE_SWITCH;
+ break;
+ case 7:
+ only_flag = 1;
+ only_type = IB_NODE_CA;
+ break;
+ case 'S':
+ case 'G':
+ guid_str = optarg;
+ guid = (uint64_t) strtoull(guid_str, 0, 0);
+ break;
+ case 'D':
+ dr_path = strdup(optarg);
+ break;
+ case 'a':
+ all = 1;
+ break;
+ case 'n':
+ cfg->max_hops = strtoul(optarg, NULL, 0);
+ break;
+ case 'd':
+ down_links_only = 1;
+ break;
+ case 'l':
+ line_mode = 1;
+ break;
+ case 'p':
+ add_sw_settings = 1;
+ break;
+ case 'R': /* nop */
+ break;
+ case 'o':
+ cfg->max_smps = strtoul(optarg, NULL, 0);
+ break;
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ struct ibnd_config config = { 0 };
+ int rc = 0;
+ int resolved = -1;
+ ibnd_fabric_t *fabric = NULL;
+ ibnd_fabric_t *diff_fabric = NULL;
+ struct ibmad_port *ibmad_port;
+ ib_portid_t port_id = { 0 };
+ uint8_t ni[IB_SMP_DATA_SIZE] = { 0 };
+ int mgmt_classes[3] =
+ { IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS };
+
+ const struct ibdiag_opt opts[] = {
+ {"node-name-map", 1, 1, "<file>", "node name map file"},
+ {"switch", 'S', 1, "<port_guid>",
+ "start partial scan at the port specified by <port_guid> (hex format)"},
+ {"port-guid", 'G', 1, "<port_guid>",
+ "(same as -S)"},
+ {"Direct", 'D', 1, "<dr_path>",
+ "start partial scan at the port specified by <dr_path>"},
+ {"all", 'a', 0, NULL,
+ "print all nodes found in a partial fabric scan"},
+ {"hops", 'n', 1, "<hops>",
+ "Number of hops to include away from specified node"},
+ {"down", 'd', 0, NULL, "print only down links"},
+ {"line", 'l', 0, NULL,
+ "(line mode) print all information for each link on a single line"},
+ {"additional", 'p', 0, NULL,
+ "print additional port settings (PktLifeTime, HoqLife, VLStallCount)"},
+ {"load-cache", 2, 1, "<file>",
+ "filename of ibnetdiscover cache to load"},
+ {"diff", 3, 1, "<file>",
+ "filename of ibnetdiscover cache to diff"},
+ {"diffcheck", 4, 1, "<key(s)>",
+ "specify checks to execute for --diff"},
+ {"filterdownports", 5, 1, "<file>",
+ "filename of ibnetdiscover cache to filter downports"},
+ {"outstanding_smps", 'o', 1, NULL,
+ "specify the number of outstanding SMP's which should be "
+ "issued during the scan"},
+ {"switches-only", 6, 0, NULL,
+ "Output only switches"},
+ {"cas-only", 7, 0, NULL,
+ "Output only CAs"},
+ {0}
+ };
+ char usage_args[] = "";
+
+ ibdiag_process_opts(argc, argv, &config, "aDdGgKLlnpRS", opts,
+ process_opt, usage_args, NULL);
+
+ argc -= optind;
+ argv += optind;
+
+ ibmad_port = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 3);
+ if (!ibmad_port) {
+ fprintf(stderr, "Failed to open %s port %d\n", ibd_ca,
+ ibd_ca_port);
+ exit(1);
+ }
+
+ smp_mkey_set(ibmad_port, ibd_mkey);
+
+ if (ibd_timeout) {
+ mad_rpc_set_timeout(ibmad_port, ibd_timeout);
+ config.timeout_ms = ibd_timeout;
+ }
+
+ config.flags = ibd_ibnetdisc_flags;
+ config.mkey = ibd_mkey;
+
+ node_name_map = open_node_name_map(node_name_map_file);
+
+ if (dr_path && load_cache_file) {
+ mad_rpc_close_port(ibmad_port);
+ fprintf(stderr, "Cannot specify cache and direct route path\n");
+ exit(1);
+ }
+
+ if (dr_path) {
+ /* only scan part of the fabric */
+ if ((resolved =
+ resolve_portid_str(ibd_ca, ibd_ca_port, &port_id, dr_path,
+ IB_DEST_DRPATH, NULL, ibmad_port)) < 0)
+ IBWARN("Failed to resolve %s; attempting full scan",
+ dr_path);
+ } else if (guid_str) {
+ if ((resolved =
+ resolve_portid_str(ibd_ca, ibd_ca_port, &port_id,
+ guid_str, IB_DEST_GUID, NULL,
+ ibmad_port)) < 0)
+ IBWARN("Failed to resolve %s; attempting full scan\n",
+ guid_str);
+ }
+
+ if (!smp_query_via(ni, &port_id, IB_ATTR_NODE_INFO, 0,
+ ibd_timeout, ibmad_port)){
+ mad_rpc_close_port(ibmad_port);
+ fprintf(stderr,
+ "Failed to get local Node Info\n");
+ exit(1);
+ }
+ mad_rpc_close_port(ibmad_port);
+
+ if (diff_cache_file &&
+ !(diff_fabric = ibnd_load_fabric(diff_cache_file, 0)))
+ IBEXIT("loading cached fabric for diff failed\n");
+
+ if (filterdownports_cache_file &&
+ !(filterdownports_fabric = ibnd_load_fabric(filterdownports_cache_file, 0)))
+ IBEXIT("loading cached fabric for filterdownports failed\n");
+
+ if (load_cache_file) {
+ if ((fabric = ibnd_load_fabric(load_cache_file, 0)) == NULL) {
+ fprintf(stderr, "loading cached fabric failed\n");
+ exit(1);
+ }
+ } else {
+ if (resolved >= 0) {
+ if (!config.max_hops)
+ config.max_hops = 1;
+ if (!(fabric =
+ ibnd_discover_fabric(ibd_ca, ibd_ca_port, &port_id, &config)))
+ IBWARN("Partial fabric scan failed;"
+ " attempting full scan\n");
+ }
+
+ if (!fabric &&
+ !(fabric = ibnd_discover_fabric(ibd_ca, ibd_ca_port, NULL, &config))) {
+ fprintf(stderr, "discover failed\n");
+ rc = 1;
+ goto close_port;
+ }
+ }
+
+ if (!all && guid_str) {
+ ibnd_port_t *p = ibnd_find_port_guid(fabric, guid);
+ if (p && (!only_flag || p->node->type == only_type)) {
+ ibnd_node_t *n = p->node;
+ if (diff_fabric)
+ diff_node(n, diff_fabric, fabric);
+ else
+ print_node(n, NULL);
+ }
+ else
+ fprintf(stderr, "Failed to find port: %s\n", guid_str);
+ } else if (!all && dr_path) {
+ ibnd_port_t *p = NULL;
+ mad_decode_field(ni, IB_NODE_PORT_GUID_F, &(guid));
+
+ p = ibnd_find_port_guid(fabric, guid);
+ if (p && (!only_flag || p->node->type == only_type)) {
+ ibnd_node_t *n = p->node;
+ if (diff_fabric)
+ diff_node(n, diff_fabric, fabric);
+ else
+ print_node(n, NULL);
+ }
+ else
+ fprintf(stderr, "Failed to find port: %s\n", dr_path);
+ } else {
+ if (diff_fabric)
+ diff_node(NULL, diff_fabric, fabric);
+ else {
+ if (only_flag)
+ ibnd_iter_nodes_type(fabric, print_node,
+ only_type, NULL);
+ else
+ ibnd_iter_nodes(fabric, print_node, NULL);
+ }
+ }
+
+ ibnd_destroy_fabric(fabric);
+ if (diff_fabric)
+ ibnd_destroy_fabric(diff_fabric);
+
+close_port:
+ close_node_name_map(node_name_map);
+ exit(rc);
+}
diff --git a/contrib/ofed/infiniband-diags/src/ibmirror.c b/contrib/ofed/infiniband-diags/src/ibmirror.c
new file mode 100644
index 000000000000..3dec71c4e529
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/src/ibmirror.c
@@ -0,0 +1,538 @@
+/*
+ * Copyright (c) 2004-2009 Voltaire Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <netinet/in.h>
+
+#include <infiniband/umad.h>
+#include <infiniband/mad.h>
+
+#include "ibdiag_common.h"
+
+#define IB_MLX_VENDOR_CLASS 10
+
+/* Vendor specific Attribute IDs */
+#define IB_MLX_IS3_GENERAL_INFO 0x17
+
+#define MAX_SWITCH_PORTS (36+1)
+static char mtx_ports[MAX_SWITCH_PORTS] = {0};
+static char mrx_ports[MAX_SWITCH_PORTS] = {0};
+static char str[4096];
+static uint8_t buf[256];
+
+#define ATTRID_PM_ROUTE 0xff30
+#define ATTRID_PM_FILTER 0xff31
+#define ATTRID_PM_PORTS 0xff32
+#define ATTRID_LOSSY_CFG 0xff80
+
+enum mirror_type {
+ MT_DISABLED = 0,
+ MT_MIRROR_NATIVE = 2,
+ MT_DROP = 5,
+ MT_MIRROR_ENCAP = 6,
+ MT_MIRROR_DROP = 7
+};
+
+enum mirror_port {
+ MP_DISABLED = 0,
+ MP_MIRROR_FILTER = 1,
+ MP_MIRROR_ALWAYS = 2,
+ MP_MIRROR_FILTER_NOT = 3,
+ MT_MIRROR_AS_RX = 1
+};
+
+#define PM_ENCAP_ETHERTYPE 0x1123
+
+struct ibmad_port *srcport;
+
+typedef struct {
+ uint16_t hw_revision;
+ uint16_t device_id;
+ uint8_t reserved[24];
+ uint32_t uptime;
+} is3_hw_info_t;
+
+typedef struct {
+ uint8_t resv1;
+ uint8_t major;
+ uint8_t minor;
+ uint8_t sub_minor;
+ uint32_t build_id;
+ uint8_t month;
+ uint8_t day;
+ uint16_t year;
+ uint16_t resv2;
+ uint16_t hour;
+ uint8_t psid[16];
+ uint32_t ini_file_version;
+} is3_fw_info_t;
+
+typedef struct {
+ uint8_t resv1;
+ uint8_t major;
+ uint8_t minor;
+ uint8_t sub_minor;
+ uint8_t resv2[28];
+} is3_sw_info_t;
+
+typedef struct {
+ uint8_t reserved[8];
+ is3_hw_info_t hw_info;
+ is3_fw_info_t fw_info;
+ is3_sw_info_t sw_info;
+} is3_general_info_t;
+
+typedef struct {
+ uint16_t ignore_buffer_mask;
+ uint16_t ignore_credit_mask;
+} lossy_config_t;
+
+static int mirror_query, mirror_dport, mirror_dlid, mirror_clear, mirror_sl, lossy_set;
+static int set_mtx, set_mrx, packet_size = 0xfff;
+
+static int parse_ports(char *ports_str, char *ports_array)
+{
+ int num, i;
+ char *str = strdup(ports_str);
+ char *token = strtok(str, ",");
+ for (i = 0; i < MAX_SWITCH_PORTS && token; i++) {
+ num = strtoul(token, NULL, 0);
+ if (num > 0 && num < MAX_SWITCH_PORTS)
+ ports_array[num] = 1;
+
+ token = strtok(NULL, ",");
+ }
+ free(str);
+ return 0;
+}
+
+void port_mirror_route(ib_portid_t * portid, int query, int clear)
+{
+ int mirror_type;
+
+ memset(&buf, 0, sizeof(buf));
+
+ if (clear) {
+ if (!smp_set_via(buf, portid, ATTRID_PM_ROUTE, 0, 0, srcport))
+ IBEXIT("Clear port mirror route set failed");
+ return;
+ }
+
+ if (query) {
+ if (!smp_query_via(buf, portid, ATTRID_PM_ROUTE, 0, 0, srcport))
+ IBEXIT("Read port mirror route get failed");
+ mad_decode_field(buf, IB_PMR_MT_F, &mirror_type);
+ if (mirror_type == MT_MIRROR_ENCAP && mirror_dlid == 0)
+ mad_decode_field(buf, IB_PMR_LRH_DLID_F, &mirror_dlid);
+ if (mirror_type == MT_MIRROR_NATIVE && mirror_dport == 0)
+ mad_decode_field(buf, IB_PMR_NM_PORT_F, &mirror_dport);
+ goto Exit;
+ }
+
+ /* Port Mirror Route */
+ mad_set_field(buf, 0, IB_PMR_ENCAP_RAW_ETH_TYPE_F, PM_ENCAP_ETHERTYPE);
+
+ if (mirror_dlid == 0) {
+ /* Can not truncate mirrored packets in local mode */
+ mad_set_field(buf, 0, IB_PMR_MAX_MIRROR_LEN_F, 0xfff);
+ mad_set_field(buf, 0, IB_PMR_MT_F, MT_MIRROR_NATIVE);
+ mad_set_field(buf, 0, IB_PMR_NM_PORT_F, mirror_dport);
+ }
+ else { /* remote mirror */
+ /* convert size to dwords */
+ packet_size = packet_size / 4 + 1;
+ mad_set_field(buf, 0, IB_PMR_MAX_MIRROR_LEN_F, packet_size);
+ mad_set_field(buf, 0, IB_PMR_MT_F, MT_MIRROR_ENCAP);
+ mad_set_field(buf, 0, IB_PMR_LRH_SL_F, mirror_sl);
+ mad_set_field(buf, 0, IB_PMR_LRH_DLID_F, mirror_dlid);
+ mad_set_field(buf, 0, IB_PMR_LRH_SLID_F, portid->lid);
+ }
+
+ if (!smp_set_via(buf, portid, ATTRID_PM_ROUTE, 0, 0, srcport))
+ IBEXIT("port mirror route set failed");
+
+Exit:
+ mad_dump_portmirror_route(str, sizeof str, buf, sizeof buf);
+ printf("Port Mirror Route\n%s", str);
+}
+
+void port_mirror_ports(ib_portid_t * portid, int query, int clear)
+{
+ int p, rqf, tqf, rqv, tqv;
+
+ memset(&buf, 0, sizeof(buf));
+
+ if (clear) {
+ if (!smp_set_via(buf, portid, ATTRID_PM_PORTS, 0, 0, srcport))
+ IBEXIT("Clear port mirror ports set failed");
+ return;
+ }
+
+ if (query) {
+ if (!smp_query_via(buf, portid, ATTRID_PM_PORTS, 0, 0, srcport))
+ IBEXIT("Read port mirror ports get failed");
+ goto Exit;
+ }
+
+ /* Port Mirror Ports */
+ rqf = IB_PMP_RQ_1_F;
+ tqf = IB_PMP_TQ_1_F;
+
+ for (p = 1; p < MAX_SWITCH_PORTS; p++) {
+ rqv = mrx_ports[p] ? MP_MIRROR_ALWAYS : MP_DISABLED;
+ tqv = mtx_ports[p] ? MP_MIRROR_ALWAYS : MT_MIRROR_AS_RX;
+ mad_set_field(buf, 0, rqf, rqv);
+ mad_set_field(buf, 0, tqf, tqv);
+ rqf += 2;
+ tqf += 2;
+ }
+
+ if (!smp_set_via(buf, portid, ATTRID_PM_PORTS, 0, 0, srcport))
+ IBEXIT("port mirror ports set failed");
+
+Exit:
+ mad_dump_portmirror_ports(str, sizeof str, buf, sizeof buf);
+ printf("Port Mirror Ports\n%s", str);
+}
+
+int get_out_port(ib_portid_t* portid)
+{
+ int block;
+ int offset;
+
+ if (mirror_dlid) {
+ block = mirror_dlid / IB_SMP_DATA_SIZE;
+ offset = mirror_dlid - block * IB_SMP_DATA_SIZE;
+ /* get out port from lft */
+ if (!smp_query_via(buf, portid, IB_ATTR_LINEARFORWTBL, block, 0, srcport))
+ IBEXIT("linear forwarding table get failed");
+ block = mirror_dlid / IB_SMP_DATA_SIZE;
+ offset = mirror_dlid - block * IB_SMP_DATA_SIZE;
+ return buf[offset];
+ }
+ else
+ return mirror_dport;
+}
+
+int get_peer(ib_portid_t* portid, int outport, int* peerlid, int* peerport)
+{
+ ib_portid_t selfportid = { 0 };
+ ib_portid_t peerportid = { 0 };
+ int selfport = 0;
+
+ /* set peerportid for peer port */
+ memcpy(&peerportid, portid, sizeof(peerportid));
+ peerportid.drpath.cnt = 1;
+ peerportid.drpath.p[1] = outport;
+ if (ib_resolve_self_via(&selfportid, &selfport, 0, srcport) < 0)
+ IBEXIT("failed to resolve self portid");
+ peerportid.drpath.drslid = (uint16_t) selfportid.lid;
+ peerportid.drpath.drdlid = 0xffff;
+ if (!smp_query_via(buf, &peerportid, IB_ATTR_PORT_INFO, 0, 0, srcport))
+ IBEXIT("get peer portinfo failed - unable to configure lossy\n");
+
+ mad_decode_field(buf, IB_PORT_LID_F, peerlid);
+ mad_decode_field(buf, IB_PORT_LOCAL_PORT_F, peerport);
+
+ return 0;
+}
+
+int get_mirror_vl(ib_portid_t* portid, int outport)
+{
+ ib_slvl_table_t * p_slvl_tbl;
+ int portnum;
+ int vl;
+
+ /* hack; assume all sl2vl mappings are the same for any in port and outport */
+ portnum = (1 << 8) | outport;
+
+ /* get sl2vl mapping */
+ if (!smp_query_via(buf, portid, IB_ATTR_SLVL_TABLE, portnum, 0, srcport))
+ IBEXIT("slvl query failed");
+
+ p_slvl_tbl = (ib_slvl_table_t *) buf;
+ vl = ib_slvl_table_get(p_slvl_tbl, mirror_sl);
+ printf("mirror_sl %d, mirror_vl %d\n", mirror_sl, vl);
+ return vl;
+}
+
+int lossy_config(ib_portid_t* portid, int query, int clear)
+{
+ int outport;
+ int peerport;
+ int attr_mod;
+ uint8_t mirror_vl;
+ ib_portid_t peerportid = { 0 };
+ ib_portid_t * p_portid;
+ lossy_config_t local_lossy_cfg;
+ lossy_config_t peer_lossy_cfg;
+ lossy_config_t lossy_cfg;
+
+ outport = get_out_port(portid);
+ if (outport == 0)
+ IBEXIT("get_out_port failed, mirror_dlid and mirror_dport are 0");
+
+ get_peer(portid, outport, &peerportid.lid, &peerport);
+
+ printf("local lid %d / port %d\n", portid->lid, outport);
+ printf("peer lid %d / port %d\n", peerportid.lid, peerport);
+
+ mirror_vl = get_mirror_vl(portid, outport);
+
+ /* read local lossy configuration */
+ if (!smp_query_via(buf, portid, ATTRID_LOSSY_CFG, outport, 0, srcport))
+ IBEXIT("get lossy config from lid %d port %d failed - not supported\n",
+ portid->lid, outport);
+ memcpy(&local_lossy_cfg, buf, sizeof(local_lossy_cfg));
+
+ /* read peer lossy configuration */
+ if (!smp_query_via(buf, &peerportid, ATTRID_LOSSY_CFG, peerport, 0, srcport))
+ IBEXIT("get lossy config from lid %d port %d failed - not supported\n",
+ peerportid.lid, peerport);
+ memcpy(&peer_lossy_cfg, buf, sizeof(peer_lossy_cfg));
+
+ if (query) {
+ printf("local port lid %d port %d ignore_buffer 0x%04x, ignore_credit 0x%04x\n",
+ portid->lid, outport,
+ ntohs(local_lossy_cfg.ignore_buffer_mask), ntohs(local_lossy_cfg.ignore_credit_mask));
+ printf("peer port lid %d port %d ignore_buffer 0x%04x, ignore_credit 0x%04x\n",
+ peerportid.lid, peerport,
+ ntohs(peer_lossy_cfg.ignore_buffer_mask), ntohs(peer_lossy_cfg.ignore_credit_mask));
+ return 0;
+ }
+
+ /* VLs 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 */
+ /* ignore Buf Overrun ignore Credits */
+ /* when mirror activated set ignore buffer overrun on peer port */
+ /* when mirror is de-activated clear ignore credits on local port */
+ memset(&buf, 0, sizeof(buf));
+ if (clear) {
+ p_portid = portid;
+ attr_mod = outport;
+ } else {
+ /* set buffer overrun on peer port */
+ p_portid = &peerportid;
+ attr_mod = peerport;
+ lossy_cfg.ignore_buffer_mask = htons(1<<mirror_vl);
+ lossy_cfg.ignore_credit_mask = 0;
+ memcpy(&buf, &lossy_cfg, sizeof(lossy_cfg));
+ }
+ if (!smp_set_via(buf, p_portid, ATTRID_LOSSY_CFG, attr_mod, 0, srcport))
+ IBEXIT("%s lossy config on lid %d failed\n", clear?"clear":"set", p_portid->lid);
+
+ /* when mirror activated set ignore credit on local port */
+ /* when mirror de-activated clear buffer overrun on peer */
+ memset(&buf, 0, sizeof(buf));
+ if (clear) {
+ p_portid = &peerportid;
+ attr_mod = peerport;
+ } else {
+ /* set ignore credit on local port */
+ p_portid = portid;
+ attr_mod = outport;
+ lossy_cfg.ignore_credit_mask = htons(1<<mirror_vl);
+ lossy_cfg.ignore_buffer_mask = 0;
+ memcpy(&buf, &lossy_cfg, sizeof(lossy_cfg));
+ }
+ if (!smp_set_via(buf, p_portid, ATTRID_LOSSY_CFG, attr_mod, 0, srcport))
+ IBEXIT("%s lossy config on lid %d failed\n", clear?"clear":"set", p_portid->lid);
+
+ return 0;
+}
+
+int mirror_config(ib_portid_t* portid, int query, int clear)
+{
+ port_mirror_route(portid, query, clear);
+ /* port_mirror_filter(portid, query, clear); */
+ port_mirror_ports(portid, query, clear);
+
+ return 0;
+}
+
+static int process_opt(void *context, int ch, char *optarg)
+{
+ switch (ch) {
+ case 'p':
+ mirror_dport = strtoul(optarg, NULL, 0);
+ break;
+ case 'S':
+ packet_size = strtoul(optarg, NULL, 0);
+ break;
+ case 'l':
+ mirror_sl = strtoul(optarg, NULL, 0);
+ break;
+ case 'L':
+ mirror_dlid = strtoul(optarg, NULL, 0);
+ break;
+ case 'R':
+ set_mrx = 1;
+ if (-1 == parse_ports(optarg, mrx_ports))
+ return -1;
+ break;
+ case 'T':
+ set_mtx = 1;
+ if (-1 == parse_ports(optarg, mtx_ports))
+ return -1;
+ break;
+ case 'D':
+ mirror_clear = 1;
+ break;
+ case 'Q':
+ mirror_query = 1;
+ break;
+ case 'y':
+ lossy_set = 1;
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ int mgmt_classes[4] = { IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS,
+ IB_MLX_VENDOR_CLASS
+ };
+ ib_portid_t portid = { 0 };
+ int port = 0;
+ ib_vendor_call_t call;
+ is3_general_info_t *gi;
+ uint32_t fw_ver;
+ char op_str[32];
+
+ const struct ibdiag_opt opts[] = {
+ {"dport", 'p', 1, "<port>", "set mirror destination port"},
+ {"dlid", 'L', 1, "<dlid>", "set mirror destination LID"},
+ {"sl", 'l', 1, "<sl>", "set mirror SL"},
+ {"size", 'S', 1, "<size>", "set packet size"},
+ {"rxports", 'R', 1, NULL, "mirror receive port list"},
+ {"txports", 'T', 1, NULL, "mirror transmit port list"},
+ {"clear", 'D', 0, NULL, "clear ports mirroring"},
+ {"query", 'Q', 0, NULL, "read mirror configuration"},
+ {"lossy", 'y', 0, NULL, "set lossy configuration on out port"},
+ {0}
+ };
+
+ char usage_args[] = "<lid>";
+ const char *usage_examples[] = {
+ "-R 1,2,3 -T 2,5 -l1 -L25 -S100 <lid>\t# configure mirror ports",
+ "-D <lid> \t# clear mirror configuration",
+ "-Q <lid>\t# read mirror configuration",
+ NULL
+ };
+
+ ibdiag_process_opts(argc, argv, NULL, "GDLs", opts, process_opt,
+ usage_args, usage_examples);
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc == 0)
+ ibdiag_show_usage();
+
+ srcport = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 4);
+ if (!srcport)
+ IBEXIT("Failed to open '%s' port '%d'", ibd_ca, ibd_ca_port);
+
+ if (argc) {
+ if (ib_resolve_portid_str_via(&portid, argv[0], ibd_dest_type,
+ ibd_sm_id, srcport) < 0)
+ IBEXIT("can't resolve destination port %s", argv[0]);
+ }
+
+
+ memset(&buf, 0, sizeof(buf));
+ memset(&call, 0, sizeof(call));
+ call.mgmt_class = IB_MLX_VENDOR_CLASS;
+ call.method = IB_MAD_METHOD_GET;
+ call.timeout = ibd_timeout;
+ call.attrid = IB_MLX_IS3_GENERAL_INFO;
+ if (!ib_vendor_call_via(&buf, &portid, &call, srcport))
+ IBEXIT("failed to read vendor info");
+ gi = (is3_general_info_t *) & buf;
+ if (ntohs(gi->hw_info.device_id) != 0x1b3)
+ IBEXIT("device id 0x%x does not support mirroring", ntohs(gi->hw_info.device_id));
+
+ fw_ver = gi->fw_info.major * 100000 + gi->fw_info.minor * 1000 + gi->fw_info.sub_minor;
+ printf("FW version %08d\n", fw_ver);
+ if (lossy_set && fw_ver < 704000)
+ IBEXIT("FW version %d.%d.%d does not support lossy config",
+ gi->fw_info.major, gi->fw_info.minor, gi->fw_info.sub_minor);
+
+ if (ibdebug) {
+ printf( "switch_lid = %d\n"
+ "mirror_clear = %d\n"
+ "mirror_dlid = %d\n"
+ "mirror_sl = %d\n"
+ "mirror_port = %d\n",
+ portid.lid, mirror_clear, mirror_dlid,
+ mirror_sl, mirror_dport);
+
+ for (port = 1; port < MAX_SWITCH_PORTS; port++) {
+ if (mtx_ports[port])
+ printf("TX: %d\n",port);
+ else if(mrx_ports[port])
+ printf("RX: %d\n",port);
+ }
+ }
+
+ if (mirror_clear)
+ strcpy(op_str, "Clear");
+ else if (mirror_query)
+ strcpy(op_str, "Read");
+ else if (!mirror_dport && !mirror_dlid)
+ IBEXIT("Mirror remote LID and local port are zero");
+ else if (!set_mtx && !set_mrx)
+ IBEXIT("Mirror Rx and Tx ports not selected");
+ else
+ strcpy(op_str, "Set");
+
+ printf("\n%s Mirror Configuration\n", op_str);
+ mirror_config(&portid, mirror_query, mirror_clear);
+
+ if (lossy_set) {
+ printf("%s Lossy Configuration\n", op_str);
+ lossy_config(&portid, mirror_query, mirror_clear);
+ }
+
+ mad_rpc_close_port(srcport);
+ exit(0);
+}
diff --git a/contrib/ofed/infiniband-diags/src/ibnetdiscover.c b/contrib/ofed/infiniband-diags/src/ibnetdiscover.c
new file mode 100644
index 000000000000..f81d03bb8264
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/src/ibnetdiscover.c
@@ -0,0 +1,1157 @@
+/*
+ * Copyright (c) 2004-2009 Voltaire Inc. All rights reserved.
+ * Copyright (c) 2007 Xsigo Systems Inc. All rights reserved.
+ * Copyright (c) 2008 Lawrence Livermore National Lab. All rights reserved.
+ * Copyright (c) 2010,2011 Mellanox Technologies LTD. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <string.h>
+#include <getopt.h>
+#include <inttypes.h>
+
+#include <infiniband/umad.h>
+#include <infiniband/mad.h>
+#include <complib/cl_nodenamemap.h>
+#include <infiniband/ibnetdisc.h>
+
+#include "ibdiag_common.h"
+
+#define LIST_CA_NODE (1 << IB_NODE_CA)
+#define LIST_SWITCH_NODE (1 << IB_NODE_SWITCH)
+#define LIST_ROUTER_NODE (1 << IB_NODE_ROUTER)
+
+#define DIFF_FLAG_SWITCH 0x01
+#define DIFF_FLAG_CA 0x02
+#define DIFF_FLAG_ROUTER 0x04
+#define DIFF_FLAG_PORT_CONNECTION 0x08
+#define DIFF_FLAG_LID 0x10
+#define DIFF_FLAG_NODE_DESCRIPTION 0x20
+
+#define DIFF_FLAG_DEFAULT (DIFF_FLAG_SWITCH | DIFF_FLAG_CA | DIFF_FLAG_ROUTER \
+ | DIFF_FLAG_PORT_CONNECTION)
+
+static FILE *f;
+
+static char *node_name_map_file = NULL;
+static nn_map_t *node_name_map = NULL;
+static char *cache_file = NULL;
+static char *load_cache_file = NULL;
+static char *diff_cache_file = NULL;
+static unsigned diffcheck_flags = DIFF_FLAG_DEFAULT;
+
+static int report_max_hops = 0;
+static int full_info;
+
+/**
+ * Define our own conversion functions to maintain compatibility with the old
+ * ibnetdiscover which did not use the ibmad conversion functions.
+ */
+char *dump_linkspeed_compat(uint32_t speed)
+{
+ switch (speed) {
+ case 1:
+ return ("SDR");
+ break;
+ case 2:
+ return ("DDR");
+ break;
+ case 4:
+ return ("QDR");
+ break;
+ }
+ return ("???");
+}
+
+char *dump_linkspeedext_compat(uint32_t espeed, uint32_t speed, uint32_t fdr10)
+{
+ switch (espeed) {
+ case 0:
+ if (fdr10 & FDR10)
+ return ("FDR10");
+ else
+ return dump_linkspeed_compat(speed);
+ break;
+ case 1:
+ return ("FDR");
+ break;
+ case 2:
+ return ("EDR");
+ break;
+ }
+ return ("???");
+}
+
+char *dump_linkwidth_compat(uint32_t width)
+{
+ switch (width) {
+ case 1:
+ return ("1x");
+ break;
+ case 2:
+ return ("4x");
+ break;
+ case 4:
+ return ("8x");
+ break;
+ case 8:
+ return ("12x");
+ break;
+ case 16:
+ return ("2x");
+ break;
+ }
+ return ("??");
+}
+
+static inline const char *ports_nt_str_compat(ibnd_node_t * node)
+{
+ switch (node->type) {
+ case IB_NODE_SWITCH:
+ return "SW";
+ case IB_NODE_CA:
+ return "CA";
+ case IB_NODE_ROUTER:
+ return "RT";
+ }
+ return "??";
+}
+
+char *node_name(ibnd_node_t * node)
+{
+ static char buf[256];
+
+ switch (node->type) {
+ case IB_NODE_SWITCH:
+ sprintf(buf, "\"%s", "S");
+ break;
+ case IB_NODE_CA:
+ sprintf(buf, "\"%s", "H");
+ break;
+ case IB_NODE_ROUTER:
+ sprintf(buf, "\"%s", "R");
+ break;
+ default:
+ sprintf(buf, "\"%s", "?");
+ break;
+ }
+ sprintf(buf + 2, "-%016" PRIx64 "\"", node->guid);
+
+ return buf;
+}
+
+void list_node(ibnd_node_t * node, void *user_data)
+{
+ char *node_type;
+ char *nodename = remap_node_name(node_name_map, node->guid,
+ node->nodedesc);
+
+ switch (node->type) {
+ case IB_NODE_SWITCH:
+ node_type = "Switch";
+ break;
+ case IB_NODE_CA:
+ node_type = "Ca";
+ break;
+ case IB_NODE_ROUTER:
+ node_type = "Router";
+ break;
+ default:
+ node_type = "???";
+ break;
+ }
+ fprintf(f,
+ "%s\t : 0x%016" PRIx64
+ " ports %d devid 0x%x vendid 0x%x \"%s\"\n", node_type,
+ node->guid, node->numports, mad_get_field(node->info, 0,
+ IB_NODE_DEVID_F),
+ mad_get_field(node->info, 0, IB_NODE_VENDORID_F), nodename);
+
+ free(nodename);
+}
+
+void list_nodes(ibnd_fabric_t * fabric, int list)
+{
+ if (list & LIST_CA_NODE)
+ ibnd_iter_nodes_type(fabric, list_node, IB_NODE_CA, NULL);
+ if (list & LIST_SWITCH_NODE)
+ ibnd_iter_nodes_type(fabric, list_node, IB_NODE_SWITCH, NULL);
+ if (list & LIST_ROUTER_NODE)
+ ibnd_iter_nodes_type(fabric, list_node, IB_NODE_ROUTER, NULL);
+}
+
+void out_ids(ibnd_node_t * node, int group, char *chname, char *out_prefix)
+{
+ uint64_t sysimgguid =
+ mad_get_field64(node->info, 0, IB_NODE_SYSTEM_GUID_F);
+
+ fprintf(f, "\n%svendid=0x%x\n", out_prefix ? out_prefix : "",
+ mad_get_field(node->info, 0, IB_NODE_VENDORID_F));
+ fprintf(f, "%sdevid=0x%x\n", out_prefix ? out_prefix : "",
+ mad_get_field(node->info, 0, IB_NODE_DEVID_F));
+ if (sysimgguid)
+ fprintf(f, "%ssysimgguid=0x%" PRIx64,
+ out_prefix ? out_prefix : "", sysimgguid);
+ if (group && node->chassis && node->chassis->chassisnum) {
+ fprintf(f, "\t\t# Chassis %d", node->chassis->chassisnum);
+ if (chname)
+ fprintf(f, " (%s)", clean_nodedesc(chname));
+ if (ibnd_is_xsigo_tca(node->guid) && node->ports[1] &&
+ node->ports[1]->remoteport)
+ fprintf(f, " slot %d",
+ node->ports[1]->remoteport->portnum);
+ }
+ if (sysimgguid ||
+ (group && node->chassis && node->chassis->chassisnum))
+ fprintf(f, "\n");
+}
+
+uint64_t out_chassis(ibnd_fabric_t * fabric, unsigned char chassisnum)
+{
+ uint64_t guid;
+
+ fprintf(f, "\nChassis %u", chassisnum);
+ guid = ibnd_get_chassis_guid(fabric, chassisnum);
+ if (guid)
+ fprintf(f, " (guid 0x%" PRIx64 ")", guid);
+ fprintf(f, "\n");
+ return guid;
+}
+
+void out_switch_detail(ibnd_node_t * node, char *sw_prefix)
+{
+ char *nodename = NULL;
+
+ nodename = remap_node_name(node_name_map, node->guid, node->nodedesc);
+
+ fprintf(f, "%sSwitch\t%d %s\t\t# \"%s\" %s port 0 lid %d lmc %d",
+ sw_prefix ? sw_prefix : "", node->numports, node_name(node),
+ nodename, node->smaenhsp0 ? "enhanced" : "base",
+ node->smalid, node->smalmc);
+
+ free(nodename);
+}
+
+void out_switch(ibnd_node_t * node, int group, char *chname, char *id_prefix,
+ char *sw_prefix)
+{
+ char *str;
+ char str2[256];
+
+ out_ids(node, group, chname, id_prefix);
+ fprintf(f, "%sswitchguid=0x%" PRIx64,
+ id_prefix ? id_prefix : "", node->guid);
+ fprintf(f, "(%" PRIx64 ")",
+ mad_get_field64(node->info, 0, IB_NODE_PORT_GUID_F));
+ if (group) {
+ fprintf(f, "\t# ");
+ str = ibnd_get_chassis_type(node);
+ if (str)
+ fprintf(f, "%s ", str);
+ str = ibnd_get_chassis_slot_str(node, str2, 256);
+ if (str)
+ fprintf(f, "%s", str);
+ }
+ fprintf(f, "\n");
+
+ out_switch_detail(node, sw_prefix);
+ fprintf(f, "\n");
+}
+
+void out_ca_detail(ibnd_node_t * node, char *ca_prefix)
+{
+ char *node_type;
+
+ switch (node->type) {
+ case IB_NODE_CA:
+ node_type = "Ca";
+ break;
+ case IB_NODE_ROUTER:
+ node_type = "Rt";
+ break;
+ default:
+ node_type = "???";
+ break;
+ }
+
+ fprintf(f, "%s%s\t%d %s\t\t# \"%s\"", ca_prefix ? ca_prefix : "",
+ node_type, node->numports, node_name(node),
+ clean_nodedesc(node->nodedesc));
+}
+
+void out_ca(ibnd_node_t * node, int group, char *chname, char *id_prefix,
+ char *ca_prefix)
+{
+ char *node_type;
+
+ out_ids(node, group, chname, id_prefix);
+ switch (node->type) {
+ case IB_NODE_CA:
+ node_type = "ca";
+ break;
+ case IB_NODE_ROUTER:
+ node_type = "rt";
+ break;
+ default:
+ node_type = "???";
+ break;
+ }
+
+ fprintf(f, "%s%sguid=0x%" PRIx64 "\n",
+ id_prefix ? id_prefix : "", node_type, node->guid);
+ out_ca_detail(node, ca_prefix);
+ if (group && ibnd_is_xsigo_hca(node->guid))
+ fprintf(f, " (scp)");
+ fprintf(f, "\n");
+}
+
+#define OUT_BUFFER_SIZE 16
+static char *out_ext_port(ibnd_port_t * port, int group)
+{
+ static char mapping[OUT_BUFFER_SIZE];
+
+ if (group && port->ext_portnum != 0) {
+ snprintf(mapping, OUT_BUFFER_SIZE,
+ "[ext %d]", port->ext_portnum);
+ return (mapping);
+ }
+
+ return (NULL);
+}
+
+void out_switch_port(ibnd_port_t * port, int group, char *out_prefix)
+{
+ char *ext_port_str = NULL;
+ char *rem_nodename = NULL;
+ uint32_t iwidth = mad_get_field(port->info, 0,
+ IB_PORT_LINK_WIDTH_ACTIVE_F);
+ uint32_t ispeed = mad_get_field(port->info, 0,
+ IB_PORT_LINK_SPEED_ACTIVE_F);
+ uint32_t vlcap = mad_get_field(port->info, 0,
+ IB_PORT_VL_CAP_F);
+ uint32_t fdr10 = mad_get_field(port->ext_info, 0,
+ IB_MLNX_EXT_PORT_LINK_SPEED_ACTIVE_F);
+ uint32_t cap_mask, espeed;
+
+ DEBUG("port %p:%d remoteport %p\n", port, port->portnum,
+ port->remoteport);
+ fprintf(f, "%s[%d]", out_prefix ? out_prefix : "", port->portnum);
+
+ ext_port_str = out_ext_port(port, group);
+ if (ext_port_str)
+ fprintf(f, "%s", ext_port_str);
+
+ rem_nodename = remap_node_name(node_name_map,
+ port->remoteport->node->guid,
+ port->remoteport->node->nodedesc);
+
+ ext_port_str = out_ext_port(port->remoteport, group);
+
+ if (!port->node->ports[0]) {
+ cap_mask = 0;
+ ispeed = 0;
+ espeed = 0;
+ } else {
+ cap_mask = mad_get_field(port->node->ports[0]->info, 0,
+ IB_PORT_CAPMASK_F);
+ if (cap_mask & CL_NTOH32(IB_PORT_CAP_HAS_EXT_SPEEDS))
+ espeed = mad_get_field(port->info, 0,
+ IB_PORT_LINK_SPEED_EXT_ACTIVE_F);
+ else
+ espeed = 0;
+ }
+ fprintf(f, "\t%s[%d]%s",
+ node_name(port->remoteport->node), port->remoteport->portnum,
+ ext_port_str ? ext_port_str : "");
+ if (port->remoteport->node->type != IB_NODE_SWITCH)
+ fprintf(f, "(%" PRIx64 ") ", port->remoteport->guid);
+ fprintf(f, "\t\t# \"%s\" lid %d %s%s",
+ rem_nodename,
+ port->remoteport->node->type == IB_NODE_SWITCH ?
+ port->remoteport->node->smalid :
+ port->remoteport->base_lid,
+ dump_linkwidth_compat(iwidth),
+ (ispeed != 4 && !espeed) ?
+ dump_linkspeed_compat(ispeed) :
+ dump_linkspeedext_compat(espeed, ispeed, fdr10));
+
+ if (full_info) {
+ fprintf(f, " s=%d w=%d v=%d", ispeed, iwidth, vlcap);
+ if (espeed)
+ fprintf(f, " e=%d", espeed);
+ }
+
+ if (ibnd_is_xsigo_tca(port->remoteport->guid))
+ fprintf(f, " slot %d", port->portnum);
+ else if (ibnd_is_xsigo_hca(port->remoteport->guid))
+ fprintf(f, " (scp)");
+ fprintf(f, "\n");
+
+ free(rem_nodename);
+}
+
+void out_ca_port(ibnd_port_t * port, int group, char *out_prefix)
+{
+ char *str = NULL;
+ char *rem_nodename = NULL;
+ uint32_t iwidth = mad_get_field(port->info, 0,
+ IB_PORT_LINK_WIDTH_ACTIVE_F);
+ uint32_t ispeed = mad_get_field(port->info, 0,
+ IB_PORT_LINK_SPEED_ACTIVE_F);
+ uint32_t vlcap = mad_get_field(port->info, 0,
+ IB_PORT_VL_CAP_F);
+ uint32_t fdr10 = mad_get_field(port->ext_info, 0,
+ IB_MLNX_EXT_PORT_LINK_SPEED_ACTIVE_F);
+ uint32_t cap_mask, espeed;
+
+ fprintf(f, "%s[%d]", out_prefix ? out_prefix : "", port->portnum);
+ if (port->node->type != IB_NODE_SWITCH)
+ fprintf(f, "(%" PRIx64 ") ", port->guid);
+ fprintf(f, "\t%s[%d]",
+ node_name(port->remoteport->node), port->remoteport->portnum);
+ str = out_ext_port(port->remoteport, group);
+ if (str)
+ fprintf(f, "%s", str);
+ if (port->remoteport->node->type != IB_NODE_SWITCH)
+ fprintf(f, " (%" PRIx64 ") ", port->remoteport->guid);
+
+ rem_nodename = remap_node_name(node_name_map,
+ port->remoteport->node->guid,
+ port->remoteport->node->nodedesc);
+
+ cap_mask = mad_get_field(port->info, 0, IB_PORT_CAPMASK_F);
+ if (cap_mask & CL_NTOH32(IB_PORT_CAP_HAS_EXT_SPEEDS))
+ espeed = mad_get_field(port->info, 0,
+ IB_PORT_LINK_SPEED_EXT_ACTIVE_F);
+ else
+ espeed = 0;
+
+ fprintf(f, "\t\t# lid %d lmc %d \"%s\" lid %d %s%s",
+ port->base_lid, port->lmc, rem_nodename,
+ port->remoteport->node->type == IB_NODE_SWITCH ?
+ port->remoteport->node->smalid :
+ port->remoteport->base_lid,
+ dump_linkwidth_compat(iwidth),
+ (ispeed != 4 && !espeed) ?
+ dump_linkspeed_compat(ispeed) :
+ dump_linkspeedext_compat(espeed, ispeed, fdr10));
+
+ if (full_info) {
+ fprintf(f, " s=%d w=%d v=%d", ispeed, iwidth, vlcap);
+ if (espeed)
+ fprintf(f, " e=%d", espeed);
+ }
+
+ fprintf(f, "\n");
+
+ free(rem_nodename);
+}
+
+struct iter_user_data {
+ int group;
+ int skip_chassis_nodes;
+};
+
+static void switch_iter_func(ibnd_node_t * node, void *iter_user_data)
+{
+ ibnd_port_t *port;
+ int p = 0;
+ struct iter_user_data *data = (struct iter_user_data *)iter_user_data;
+
+ DEBUG("SWITCH: node %p\n", node);
+
+ /* skip chassis based switches if flagged */
+ if (data->skip_chassis_nodes && node->chassis
+ && node->chassis->chassisnum)
+ return;
+
+ out_switch(node, data->group, NULL, NULL, NULL);
+ for (p = 1; p <= node->numports; p++) {
+ port = node->ports[p];
+ if (port && port->remoteport)
+ out_switch_port(port, data->group, NULL);
+ }
+}
+
+static void ca_iter_func(ibnd_node_t * node, void *iter_user_data)
+{
+ ibnd_port_t *port;
+ int p = 0;
+ struct iter_user_data *data = (struct iter_user_data *)iter_user_data;
+
+ DEBUG("CA: node %p\n", node);
+ /* Now, skip chassis based CAs */
+ if (data->group && node->chassis && node->chassis->chassisnum)
+ return;
+ out_ca(node, data->group, NULL, NULL, NULL);
+
+ for (p = 1; p <= node->numports; p++) {
+ port = node->ports[p];
+ if (port && port->remoteport)
+ out_ca_port(port, data->group, NULL);
+ }
+}
+
+static void router_iter_func(ibnd_node_t * node, void *iter_user_data)
+{
+ ibnd_port_t *port;
+ int p = 0;
+ struct iter_user_data *data = (struct iter_user_data *)iter_user_data;
+
+ DEBUG("RT: node %p\n", node);
+ /* Now, skip chassis based RTs */
+ if (data->group && node->chassis && node->chassis->chassisnum)
+ return;
+ out_ca(node, data->group, NULL, NULL, NULL);
+ for (p = 1; p <= node->numports; p++) {
+ port = node->ports[p];
+ if (port && port->remoteport)
+ out_ca_port(port, data->group, NULL);
+ }
+}
+
+int dump_topology(int group, ibnd_fabric_t * fabric)
+{
+ ibnd_node_t *node;
+ ibnd_port_t *port;
+ int i = 0, p = 0;
+ time_t t = time(0);
+ uint64_t chguid;
+ char *chname = NULL;
+ struct iter_user_data iter_user_data;
+
+ fprintf(f, "#\n# Topology file: generated on %s#\n", ctime(&t));
+ if (report_max_hops)
+ fprintf(f, "# Reported max hops discovered: %u\n"
+ "# Total MADs used: %u\n",
+ fabric->maxhops_discovered, fabric->total_mads_used);
+ fprintf(f, "# Initiated from node %016" PRIx64 " port %016" PRIx64 "\n",
+ fabric->from_node->guid,
+ mad_get_field64(fabric->from_node->info, 0,
+ IB_NODE_PORT_GUID_F));
+
+ /* Make pass on switches */
+ if (group) {
+ ibnd_chassis_t *ch = NULL;
+
+ /* Chassis based switches first */
+ for (ch = fabric->chassis; ch; ch = ch->next) {
+ int n = 0;
+
+ if (!ch->chassisnum)
+ continue;
+ chguid = out_chassis(fabric, ch->chassisnum);
+ chname = NULL;
+ if (ibnd_is_xsigo_guid(chguid)) {
+ for (node = ch->nodes; node;
+ node = node->next_chassis_node) {
+ if (ibnd_is_xsigo_hca(node->guid)) {
+ chname = node->nodedesc;
+ fprintf(f, "Hostname: %s\n",
+ clean_nodedesc
+ (node->nodedesc));
+ }
+ }
+ }
+
+ fprintf(f, "\n# Spine Nodes");
+ for (n = 1; n <= SPINES_MAX_NUM; n++) {
+ if (ch->spinenode[n]) {
+ out_switch(ch->spinenode[n], group,
+ chname, NULL, NULL);
+ for (p = 1;
+ p <= ch->spinenode[n]->numports;
+ p++) {
+ port =
+ ch->spinenode[n]->ports[p];
+ if (port && port->remoteport)
+ out_switch_port(port,
+ group,
+ NULL);
+ }
+ }
+ }
+ fprintf(f, "\n# Line Nodes");
+ for (n = 1; n <= LINES_MAX_NUM; n++) {
+ if (ch->linenode[n]) {
+ out_switch(ch->linenode[n], group,
+ chname, NULL, NULL);
+ for (p = 1;
+ p <= ch->linenode[n]->numports;
+ p++) {
+ port =
+ ch->linenode[n]->ports[p];
+ if (port && port->remoteport)
+ out_switch_port(port,
+ group,
+ NULL);
+ }
+ }
+ }
+
+ fprintf(f, "\n# Chassis Switches");
+ for (node = ch->nodes; node;
+ node = node->next_chassis_node) {
+ if (node->type == IB_NODE_SWITCH) {
+ out_switch(node, group, chname, NULL,
+ NULL);
+ for (p = 1; p <= node->numports; p++) {
+ port = node->ports[p];
+ if (port && port->remoteport)
+ out_switch_port(port,
+ group,
+ NULL);
+ }
+ }
+
+ }
+
+ fprintf(f, "\n# Chassis CAs");
+ for (node = ch->nodes; node;
+ node = node->next_chassis_node) {
+ if (node->type == IB_NODE_CA) {
+ out_ca(node, group, chname, NULL, NULL);
+ for (p = 1; p <= node->numports; p++) {
+ port = node->ports[p];
+ if (port && port->remoteport)
+ out_ca_port(port, group,
+ NULL);
+ }
+ }
+ }
+
+ }
+
+ } else { /* !group */
+ iter_user_data.group = group;
+ iter_user_data.skip_chassis_nodes = 0;
+ ibnd_iter_nodes_type(fabric, switch_iter_func, IB_NODE_SWITCH,
+ &iter_user_data);
+ }
+
+ chname = NULL;
+ if (group) {
+ iter_user_data.group = group;
+ iter_user_data.skip_chassis_nodes = 1;
+
+ fprintf(f, "\nNon-Chassis Nodes\n");
+
+ ibnd_iter_nodes_type(fabric, switch_iter_func, IB_NODE_SWITCH,
+ &iter_user_data);
+ }
+
+ iter_user_data.group = group;
+ iter_user_data.skip_chassis_nodes = 0;
+ /* Make pass on CAs */
+ ibnd_iter_nodes_type(fabric, ca_iter_func, IB_NODE_CA, &iter_user_data);
+
+ /* Make pass on routers */
+ ibnd_iter_nodes_type(fabric, router_iter_func, IB_NODE_ROUTER,
+ &iter_user_data);
+
+ return i;
+}
+
+void dump_ports_report(ibnd_node_t * node, void *user_data)
+{
+ int p = 0;
+ ibnd_port_t *port = NULL;
+ char *nodename = NULL;
+ char *rem_nodename = NULL;
+
+ /* for each port */
+ for (p = node->numports, port = node->ports[p]; p > 0;
+ port = node->ports[--p]) {
+ uint32_t iwidth, ispeed, fdr10, espeed, cap_mask;
+ uint8_t *info = NULL;
+ if (port == NULL)
+ continue;
+ iwidth =
+ mad_get_field(port->info, 0, IB_PORT_LINK_WIDTH_ACTIVE_F);
+ ispeed =
+ mad_get_field(port->info, 0, IB_PORT_LINK_SPEED_ACTIVE_F);
+ if (port->node->type == IB_NODE_SWITCH) {
+ if (port->node->ports[0])
+ info = (uint8_t *)&port->node->ports[0]->info;
+ }
+ else
+ info = (uint8_t *)&port->info;
+ if (info) {
+ cap_mask = mad_get_field(info, 0, IB_PORT_CAPMASK_F);
+ if (cap_mask & CL_NTOH32(IB_PORT_CAP_HAS_EXT_SPEEDS))
+ espeed = mad_get_field(port->info, 0,
+ IB_PORT_LINK_SPEED_EXT_ACTIVE_F);
+ else
+ espeed = 0;
+ } else {
+ ispeed = 0;
+ iwidth = 0;
+ espeed = 0;
+ }
+ fdr10 = mad_get_field(port->ext_info, 0,
+ IB_MLNX_EXT_PORT_LINK_SPEED_ACTIVE_F);
+ nodename = remap_node_name(node_name_map,
+ port->node->guid,
+ port->node->nodedesc);
+ fprintf(stdout, "%2s %5d %2d 0x%016" PRIx64 " %s %s",
+ ports_nt_str_compat(node),
+ node->type ==
+ IB_NODE_SWITCH ? node->smalid : port->base_lid,
+ port->portnum, port->guid,
+ dump_linkwidth_compat(iwidth),
+ (ispeed != 4 && !espeed) ?
+ dump_linkspeed_compat(ispeed) :
+ dump_linkspeedext_compat(espeed, ispeed, fdr10));
+ if (port->remoteport) {
+ rem_nodename = remap_node_name(node_name_map,
+ port->remoteport->node->guid,
+ port->remoteport->node->nodedesc);
+ fprintf(stdout,
+ " - %2s %5d %2d 0x%016" PRIx64
+ " ( '%s' - '%s' )\n",
+ ports_nt_str_compat(port->remoteport->node),
+ port->remoteport->node->type == IB_NODE_SWITCH ?
+ port->remoteport->node->smalid :
+ port->remoteport->base_lid,
+ port->remoteport->portnum,
+ port->remoteport->guid, nodename, rem_nodename);
+ free(rem_nodename);
+ } else
+ fprintf(stdout, "%36s'%s'\n", "", nodename);
+
+ free(nodename);
+ }
+}
+
+struct iter_diff_data {
+ uint32_t diff_flags;
+ ibnd_fabric_t *fabric1;
+ ibnd_fabric_t *fabric2;
+ char *fabric1_prefix;
+ char *fabric2_prefix;
+ void (*out_header) (ibnd_node_t *, int, char *, char *, char *);
+ void (*out_header_detail) (ibnd_node_t *, char *);
+ void (*out_port) (ibnd_port_t *, int, char *);
+};
+
+static void diff_iter_out_header(ibnd_node_t * node,
+ struct iter_diff_data *data,
+ int *out_header_flag)
+{
+ if (!(*out_header_flag)) {
+ (*data->out_header) (node, 0, NULL, NULL, NULL);
+ (*out_header_flag)++;
+ }
+}
+
+static void diff_ports(ibnd_node_t * fabric1_node, ibnd_node_t * fabric2_node,
+ int *out_header_flag, struct iter_diff_data *data)
+{
+ ibnd_port_t *fabric1_port;
+ ibnd_port_t *fabric2_port;
+ int p;
+
+ for (p = 1; p <= fabric1_node->numports; p++) {
+ int fabric1_out = 0, fabric2_out = 0;
+
+ fabric1_port = fabric1_node->ports[p];
+ fabric2_port = fabric2_node->ports[p];
+
+ if (data->diff_flags & DIFF_FLAG_PORT_CONNECTION) {
+ if ((fabric1_port && !fabric2_port)
+ || ((fabric1_port && fabric2_port)
+ && (fabric1_port->remoteport
+ && !fabric2_port->remoteport)))
+ fabric1_out++;
+ else if ((!fabric1_port && fabric2_port)
+ || ((fabric1_port && fabric2_port)
+ && (!fabric1_port->remoteport
+ && fabric2_port->remoteport)))
+ fabric2_out++;
+ else if ((fabric1_port && fabric2_port)
+ && ((fabric1_port->guid != fabric2_port->guid)
+ ||
+ ((fabric1_port->remoteport
+ && fabric2_port->remoteport)
+ && (fabric1_port->remoteport->guid !=
+ fabric2_port->remoteport->guid)))) {
+ fabric1_out++;
+ fabric2_out++;
+ }
+ }
+
+ if ((data->diff_flags & DIFF_FLAG_LID)
+ && fabric1_port && fabric2_port
+ && fabric1_port->base_lid != fabric2_port->base_lid) {
+ fabric1_out++;
+ fabric2_out++;
+ }
+
+ if (data->diff_flags & DIFF_FLAG_PORT_CONNECTION
+ && data->diff_flags & DIFF_FLAG_NODE_DESCRIPTION
+ && fabric1_port && fabric2_port
+ && fabric1_port->remoteport && fabric2_port->remoteport
+ && memcmp(fabric1_port->remoteport->node->nodedesc,
+ fabric2_port->remoteport->node->nodedesc,
+ IB_SMP_DATA_SIZE)) {
+ fabric1_out++;
+ fabric2_out++;
+ }
+
+ if (data->diff_flags & DIFF_FLAG_PORT_CONNECTION
+ && data->diff_flags & DIFF_FLAG_NODE_DESCRIPTION
+ && fabric1_port && fabric2_port
+ && fabric1_port->remoteport && fabric2_port->remoteport
+ && memcmp(fabric1_port->remoteport->node->nodedesc,
+ fabric2_port->remoteport->node->nodedesc,
+ IB_SMP_DATA_SIZE)) {
+ fabric1_out++;
+ fabric2_out++;
+ }
+
+ if (data->diff_flags & DIFF_FLAG_PORT_CONNECTION
+ && data->diff_flags & DIFF_FLAG_LID
+ && fabric1_port && fabric2_port
+ && fabric1_port->remoteport && fabric2_port->remoteport
+ && fabric1_port->remoteport->base_lid != fabric2_port->remoteport->base_lid) {
+ fabric1_out++;
+ fabric2_out++;
+ }
+
+ if (fabric1_out) {
+ diff_iter_out_header(fabric1_node, data,
+ out_header_flag);
+ (*data->out_port) (fabric1_port, 0,
+ data->fabric1_prefix);
+ }
+ if (fabric2_out) {
+ diff_iter_out_header(fabric1_node, data,
+ out_header_flag);
+ (*data->out_port) (fabric2_port, 0,
+ data->fabric2_prefix);
+ }
+ }
+}
+
+static void diff_iter_func(ibnd_node_t * fabric1_node, void *iter_user_data)
+{
+ struct iter_diff_data *data = iter_user_data;
+ ibnd_node_t *fabric2_node;
+ ibnd_port_t *fabric1_port;
+ int p;
+
+ DEBUG("DEBUG: fabric1_node %p\n", fabric1_node);
+
+ fabric2_node = ibnd_find_node_guid(data->fabric2, fabric1_node->guid);
+ if (!fabric2_node) {
+ (*data->out_header) (fabric1_node, 0, NULL,
+ data->fabric1_prefix,
+ data->fabric1_prefix);
+ for (p = 1; p <= fabric1_node->numports; p++) {
+ fabric1_port = fabric1_node->ports[p];
+ if (fabric1_port && fabric1_port->remoteport)
+ (*data->out_port) (fabric1_port, 0,
+ data->fabric1_prefix);
+ }
+ } else if (data->diff_flags &
+ (DIFF_FLAG_PORT_CONNECTION | DIFF_FLAG_LID
+ | DIFF_FLAG_NODE_DESCRIPTION)) {
+ int out_header_flag = 0;
+
+ if ((data->diff_flags & DIFF_FLAG_LID
+ && fabric1_node->smalid != fabric2_node->smalid) ||
+ (data->diff_flags & DIFF_FLAG_NODE_DESCRIPTION
+ && memcmp(fabric1_node->nodedesc, fabric2_node->nodedesc,
+ IB_SMP_DATA_SIZE))) {
+ (*data->out_header) (fabric1_node, 0, NULL, NULL,
+ data->fabric1_prefix);
+ (*data->out_header_detail) (fabric2_node,
+ data->fabric2_prefix);
+ fprintf(f, "\n");
+ out_header_flag++;
+ }
+
+ if (fabric1_node->numports != fabric2_node->numports) {
+ diff_iter_out_header(fabric1_node, data,
+ &out_header_flag);
+ fprintf(f, "%snumports = %d\n", data->fabric1_prefix,
+ fabric1_node->numports);
+ fprintf(f, "%snumports = %d\n", data->fabric2_prefix,
+ fabric2_node->numports);
+ return;
+ }
+
+ if (data->diff_flags & DIFF_FLAG_PORT_CONNECTION
+ || data->diff_flags & DIFF_FLAG_LID)
+ diff_ports(fabric1_node, fabric2_node, &out_header_flag,
+ data);
+ }
+}
+
+static int diff_common(ibnd_fabric_t * orig_fabric, ibnd_fabric_t * new_fabric,
+ int node_type, uint32_t diff_flags,
+ void (*out_header) (ibnd_node_t *, int, char *, char *,
+ char *),
+ void (*out_header_detail) (ibnd_node_t *, char *),
+ void (*out_port) (ibnd_port_t *, int, char *))
+{
+ struct iter_diff_data iter_diff_data;
+
+ iter_diff_data.diff_flags = diff_flags;
+ iter_diff_data.fabric1 = orig_fabric;
+ iter_diff_data.fabric2 = new_fabric;
+ iter_diff_data.fabric1_prefix = "< ";
+ iter_diff_data.fabric2_prefix = "> ";
+ iter_diff_data.out_header = out_header;
+ iter_diff_data.out_header_detail = out_header_detail;
+ iter_diff_data.out_port = out_port;
+ ibnd_iter_nodes_type(orig_fabric, diff_iter_func, node_type,
+ &iter_diff_data);
+
+ /* Do opposite diff to find existence of node types
+ * in new_fabric but not in orig_fabric.
+ *
+ * In this diff, we don't need to check port connections,
+ * lids, or node descriptions since it has already been
+ * done (i.e. checks are only done when guid exists on both
+ * orig and new).
+ */
+ iter_diff_data.diff_flags = diff_flags & ~DIFF_FLAG_PORT_CONNECTION;
+ iter_diff_data.diff_flags &= ~DIFF_FLAG_LID;
+ iter_diff_data.diff_flags &= ~DIFF_FLAG_NODE_DESCRIPTION;
+ iter_diff_data.fabric1 = new_fabric;
+ iter_diff_data.fabric2 = orig_fabric;
+ iter_diff_data.fabric1_prefix = "> ";
+ iter_diff_data.fabric2_prefix = "< ";
+ iter_diff_data.out_header = out_header;
+ iter_diff_data.out_header_detail = out_header_detail;
+ iter_diff_data.out_port = out_port;
+ ibnd_iter_nodes_type(new_fabric, diff_iter_func, node_type,
+ &iter_diff_data);
+
+ return 0;
+}
+
+int diff(ibnd_fabric_t * orig_fabric, ibnd_fabric_t * new_fabric)
+{
+ if (diffcheck_flags & DIFF_FLAG_SWITCH)
+ diff_common(orig_fabric, new_fabric, IB_NODE_SWITCH,
+ diffcheck_flags, out_switch, out_switch_detail,
+ out_switch_port);
+
+ if (diffcheck_flags & DIFF_FLAG_CA)
+ diff_common(orig_fabric, new_fabric, IB_NODE_CA,
+ diffcheck_flags, out_ca, out_ca_detail,
+ out_ca_port);
+
+ if (diffcheck_flags & DIFF_FLAG_ROUTER)
+ diff_common(orig_fabric, new_fabric, IB_NODE_ROUTER,
+ diffcheck_flags, out_ca, out_ca_detail,
+ out_ca_port);
+
+ return 0;
+}
+
+static int list, group, ports_report;
+
+static int process_opt(void *context, int ch, char *optarg)
+{
+ struct ibnd_config *cfg = context;
+ char *p;
+
+ switch (ch) {
+ case 1:
+ node_name_map_file = strdup(optarg);
+ break;
+ case 2:
+ cache_file = strdup(optarg);
+ break;
+ case 3:
+ load_cache_file = strdup(optarg);
+ break;
+ case 4:
+ diff_cache_file = strdup(optarg);
+ break;
+ case 5:
+ diffcheck_flags = 0;
+ p = strtok(optarg, ",");
+ while (p) {
+ if (!strcasecmp(p, "sw"))
+ diffcheck_flags |= DIFF_FLAG_SWITCH;
+ else if (!strcasecmp(p, "ca"))
+ diffcheck_flags |= DIFF_FLAG_CA;
+ else if (!strcasecmp(p, "router"))
+ diffcheck_flags |= DIFF_FLAG_ROUTER;
+ else if (!strcasecmp(p, "port"))
+ diffcheck_flags |= DIFF_FLAG_PORT_CONNECTION;
+ else if (!strcasecmp(p, "lid"))
+ diffcheck_flags |= DIFF_FLAG_LID;
+ else if (!strcasecmp(p, "nodedesc"))
+ diffcheck_flags |= DIFF_FLAG_NODE_DESCRIPTION;
+ else {
+ fprintf(stderr, "invalid diff check key: %s\n",
+ p);
+ return -1;
+ }
+ p = strtok(NULL, ",");
+ }
+ break;
+ case 's':
+ cfg->show_progress = 1;
+ break;
+ case 'f':
+ full_info = 1;
+ break;
+ case 'l':
+ list = LIST_CA_NODE | LIST_SWITCH_NODE | LIST_ROUTER_NODE;
+ break;
+ case 'g':
+ group = 1;
+ break;
+ case 'S':
+ list = LIST_SWITCH_NODE;
+ break;
+ case 'H':
+ list = LIST_CA_NODE;
+ break;
+ case 'R':
+ list = LIST_ROUTER_NODE;
+ break;
+ case 'p':
+ ports_report = 1;
+ break;
+ case 'm':
+ report_max_hops = 1;
+ break;
+ case 'o':
+ cfg->max_smps = strtoul(optarg, NULL, 0);
+ break;
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ struct ibnd_config config = { 0 };
+ ibnd_fabric_t *fabric = NULL;
+ ibnd_fabric_t *diff_fabric = NULL;
+
+ const struct ibdiag_opt opts[] = {
+ {"full", 'f', 0, NULL, "show full information (ports' speed and width, vlcap)"},
+ {"show", 's', 0, NULL, "show more information"},
+ {"list", 'l', 0, NULL, "list of connected nodes"},
+ {"grouping", 'g', 0, NULL, "show grouping"},
+ {"Hca_list", 'H', 0, NULL, "list of connected CAs"},
+ {"Switch_list", 'S', 0, NULL, "list of connected switches"},
+ {"Router_list", 'R', 0, NULL, "list of connected routers"},
+ {"node-name-map", 1, 1, "<file>", "node name map file"},
+ {"cache", 2, 1, "<file>",
+ "filename to cache ibnetdiscover data to"},
+ {"load-cache", 3, 1, "<file>",
+ "filename of ibnetdiscover cache to load"},
+ {"diff", 4, 1, "<file>",
+ "filename of ibnetdiscover cache to diff"},
+ {"diffcheck", 5, 1, "<key(s)>",
+ "specify checks to execute for --diff"},
+ {"ports", 'p', 0, NULL, "obtain a ports report"},
+ {"max_hops", 'm', 0, NULL,
+ "report max hops discovered by the library"},
+ {"outstanding_smps", 'o', 1, NULL,
+ "specify the number of outstanding SMP's which should be "
+ "issued during the scan"},
+ {0}
+ };
+ char usage_args[] = "[topology-file]";
+
+ ibdiag_process_opts(argc, argv, &config, "DGKLs", opts, process_opt,
+ usage_args, NULL);
+
+ f = stdout;
+
+ argc -= optind;
+ argv += optind;
+
+ if (ibd_timeout)
+ config.timeout_ms = ibd_timeout;
+
+ config.flags = ibd_ibnetdisc_flags;
+
+ if (argc && !(f = fopen(argv[0], "w")))
+ IBEXIT("can't open file %s for writing", argv[0]);
+
+ config.mkey = ibd_mkey;
+
+ node_name_map = open_node_name_map(node_name_map_file);
+
+ if (diff_cache_file &&
+ !(diff_fabric = ibnd_load_fabric(diff_cache_file, 0)))
+ IBEXIT("loading cached fabric for diff failed\n");
+
+ if (load_cache_file) {
+ if ((fabric = ibnd_load_fabric(load_cache_file, 0)) == NULL)
+ IBEXIT("loading cached fabric failed\n");
+ } else {
+ if ((fabric =
+ ibnd_discover_fabric(ibd_ca, ibd_ca_port, NULL, &config)) == NULL)
+ IBEXIT("discover failed\n");
+ }
+
+ if (ports_report)
+ ibnd_iter_nodes(fabric, dump_ports_report, NULL);
+ else if (list)
+ list_nodes(fabric, list);
+ else if (diff_fabric)
+ diff(diff_fabric, fabric);
+ else
+ dump_topology(group, fabric);
+
+ if (cache_file)
+ if (ibnd_cache_fabric(fabric, cache_file, 0) < 0)
+ IBEXIT("caching ibnetdiscover data failed\n");
+
+ ibnd_destroy_fabric(fabric);
+ if (diff_fabric)
+ ibnd_destroy_fabric(diff_fabric);
+ close_node_name_map(node_name_map);
+ exit(0);
+}
diff --git a/contrib/ofed/infiniband-diags/src/ibping.c b/contrib/ofed/infiniband-diags/src/ibping.c
new file mode 100644
index 000000000000..b371e1e64937
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/src/ibping.c
@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 2004-2009 Voltaire Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <signal.h>
+#include <getopt.h>
+
+#include <infiniband/umad.h>
+#include <infiniband/mad.h>
+#include <complib/cl_timer.h>
+
+#include "ibdiag_common.h"
+
+struct ibmad_port *srcport;
+
+static char host_and_domain[IB_VENDOR_RANGE2_DATA_SIZE];
+static char last_host[IB_VENDOR_RANGE2_DATA_SIZE];
+static ibmad_gid_t dgid;
+static int with_grh;
+
+static void get_host_and_domain(char *data, int sz)
+{
+ char *s = data;
+ int n;
+
+ if (gethostname(s, sz) < 0)
+ snprintf(s, sz, "?hostname?");
+
+ s[sz - 1] = 0;
+ if ((n = strlen(s)) >= sz)
+ return;
+ s[n] = '.';
+ s += n + 1;
+ sz -= n + 1;
+
+ if (getdomainname(s, sz) < 0)
+ snprintf(s, sz, "?domainname?");
+ if (strlen(s) == 0)
+ s[-1] = 0; /* no domain */
+}
+
+static char *ibping_serv(void)
+{
+ void *umad;
+ void *mad;
+ char *data;
+
+ DEBUG("starting to serve...");
+
+ while ((umad = mad_receive_via(0, -1, srcport))) {
+
+ if (umad_status(umad) == 0) {
+ mad = umad_get_mad(umad);
+ data = (char *)mad + IB_VENDOR_RANGE2_DATA_OFFS;
+
+ memcpy(data, host_and_domain, IB_VENDOR_RANGE2_DATA_SIZE);
+
+ DEBUG("Pong: %s", data);
+
+ if (mad_respond_via(umad, 0, 0, srcport) < 0)
+ DEBUG("respond failed");
+
+ }
+ mad_free(umad);
+ }
+
+ DEBUG("server out");
+ return 0;
+}
+
+static int oui = IB_OPENIB_OUI;
+
+static uint64_t ibping(ib_portid_t * portid, int quiet)
+{
+ char data[IB_VENDOR_RANGE2_DATA_SIZE] = { 0 };
+ ib_vendor_call_t call;
+ uint64_t start, rtt;
+
+ DEBUG("Ping..");
+
+ start = cl_get_time_stamp();
+
+ call.method = IB_MAD_METHOD_GET;
+ call.mgmt_class = IB_VENDOR_OPENIB_PING_CLASS;
+ call.attrid = 0;
+ call.mod = 0;
+ call.oui = oui;
+ call.timeout = 0;
+ memset(&call.rmpp, 0, sizeof call.rmpp);
+
+ if (!ib_vendor_call_via(data, portid, &call, srcport))
+ return ~0ull;
+
+ rtt = cl_get_time_stamp() - start;
+
+ if (!last_host[0])
+ memcpy(last_host, data, sizeof last_host);
+
+ if (!quiet)
+ printf("Pong from %s (%s): time %" PRIu64 ".%03" PRIu64 " ms\n",
+ data, portid2str(portid), rtt / 1000, rtt % 1000);
+
+ return rtt;
+}
+
+static uint64_t minrtt = ~0ull, maxrtt, total_rtt;
+static uint64_t start, total_time, replied, lost, ntrans;
+static ib_portid_t portid = { 0 };
+
+void report(int sig)
+{
+ total_time = cl_get_time_stamp() - start;
+
+ DEBUG("out due signal %d", sig);
+
+ printf("\n--- %s (%s) ibping statistics ---\n", last_host,
+ portid2str(&portid));
+ printf("%" PRIu64 " packets transmitted, %" PRIu64 " received, %" PRIu64
+ "%% packet loss, time %" PRIu64 " ms\n", ntrans, replied,
+ (lost != 0) ? lost * 100 / ntrans : 0, total_time / 1000);
+ printf("rtt min/avg/max = %" PRIu64 ".%03" PRIu64 "/%" PRIu64 ".%03"
+ PRIu64 "/%" PRIu64 ".%03" PRIu64 " ms\n",
+ minrtt == ~0ull ? 0 : minrtt / 1000,
+ minrtt == ~0ull ? 0 : minrtt % 1000,
+ replied ? total_rtt / replied / 1000 : 0,
+ replied ? (total_rtt / replied) % 1000 : 0, maxrtt / 1000,
+ maxrtt % 1000);
+
+ exit(0);
+}
+
+static int server = 0, flood = 0;
+static unsigned count = ~0;
+
+static int process_opt(void *context, int ch, char *optarg)
+{
+ switch (ch) {
+ case 'c':
+ count = strtoul(optarg, 0, 0);
+ break;
+ case 'f':
+ flood++;
+ break;
+ case 'o':
+ oui = strtoul(optarg, 0, 0);
+ break;
+ case 'S':
+ server++;
+ break;
+ case 25:
+ if (!inet_pton(AF_INET6, optarg, &dgid)) {
+ printf("dgid format is wrong!\n");
+ ibdiag_show_usage();
+ return 1;
+ }
+ with_grh = 1;
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ int mgmt_classes[1] = { IB_SA_CLASS };
+ int ping_class = IB_VENDOR_OPENIB_PING_CLASS;
+ uint64_t rtt;
+ char *err;
+
+ const struct ibdiag_opt opts[] = {
+ {"count", 'c', 1, "<num>", "stop after count packets"},
+ {"flood", 'f', 0, NULL, "flood destination"},
+ {"oui", 'o', 1, NULL, "use specified OUI number"},
+ {"Server", 'S', 0, NULL, "start in server mode"},
+ {"dgid", 25, 1, NULL, "remote gid (IPv6 format)"},
+ {0}
+ };
+ char usage_args[] = "<dest lid|guid>";
+
+ ibdiag_process_opts(argc, argv, NULL, "DKy", opts, process_opt,
+ usage_args, NULL);
+
+ argc -= optind;
+ argv += optind;
+
+ if (!argc && !server)
+ ibdiag_show_usage();
+
+ srcport = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 1);
+ if (!srcport)
+ IBEXIT("Failed to open '%s' port '%d'", ibd_ca, ibd_ca_port);
+
+ if (server) {
+ if (mad_register_server_via(ping_class, 0, 0, oui, srcport) < 0)
+ IBEXIT("can't serve class %d on this port",
+ ping_class);
+
+ get_host_and_domain(host_and_domain, sizeof host_and_domain);
+
+ if ((err = ibping_serv()))
+ IBEXIT("ibping to %s: %s", portid2str(&portid), err);
+ exit(0);
+ }
+
+ if (mad_register_client_via(ping_class, 0, srcport) < 0)
+ IBEXIT("can't register ping class %d on this port",
+ ping_class);
+
+ if (with_grh && ibd_dest_type != IB_DEST_LID)
+ IBEXIT("When using GRH, LID should be provided");
+ if (resolve_portid_str(ibd_ca, ibd_ca_port, &portid, argv[0],
+ ibd_dest_type, ibd_sm_id, srcport) < 0)
+ IBEXIT("can't resolve destination port %s", argv[0]);
+
+ if (with_grh) {
+ portid.grh_present = 1;
+ memcpy(&portid.gid, &dgid, sizeof(portid.gid));
+ }
+
+ signal(SIGINT, report);
+ signal(SIGTERM, report);
+
+ start = cl_get_time_stamp();
+
+ while (count-- > 0) {
+ ntrans++;
+ if ((rtt = ibping(&portid, flood)) == ~0ull) {
+ DEBUG("ibping to %s failed", portid2str(&portid));
+ lost++;
+ } else {
+ if (rtt < minrtt)
+ minrtt = rtt;
+ if (rtt > maxrtt)
+ maxrtt = rtt;
+ total_rtt += rtt;
+ replied++;
+ }
+
+ if (!flood)
+ sleep(1);
+ }
+
+ report(0);
+
+ mad_rpc_close_port(srcport);
+
+ exit(-1);
+}
diff --git a/contrib/ofed/infiniband-diags/src/ibportstate.c b/contrib/ofed/infiniband-diags/src/ibportstate.c
new file mode 100644
index 000000000000..06bd5d217550
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/src/ibportstate.c
@@ -0,0 +1,767 @@
+/*
+ * Copyright (c) 2004-2009 Voltaire Inc. All rights reserved.
+ * Copyright (c) 2010,2011 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 2011,2016 Oracle and/or its affiliates. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <getopt.h>
+#include <errno.h>
+
+#include <infiniband/umad.h>
+#include <infiniband/mad.h>
+
+#include "ibdiag_common.h"
+
+enum port_ops {
+ QUERY,
+ ENABLE,
+ RESET,
+ DISABLE,
+ SPEED,
+ ESPEED,
+ FDR10SPEED,
+ WIDTH,
+ DOWN,
+ ARM,
+ ACTIVE,
+ VLS,
+ MTU,
+ LID,
+ SMLID,
+ LMC,
+ MKEY,
+ MKEYLEASE,
+ MKEYPROT,
+ ON,
+ OFF
+};
+
+struct ibmad_port *srcport;
+uint64_t speed = 0; /* no state change */
+uint64_t espeed = 0; /* no state change */
+uint64_t fdr10 = 0; /* no state change */
+uint64_t width = 0; /* no state change */
+uint64_t lid;
+uint64_t smlid;
+uint64_t lmc;
+uint64_t mtu;
+uint64_t vls = 0; /* no state change */
+uint64_t mkey;
+uint64_t mkeylease;
+uint64_t mkeyprot;
+
+struct {
+ const char *name;
+ uint64_t *val;
+ int set;
+} port_args[] = {
+ {"query", NULL, 0}, /* QUERY */
+ {"enable", NULL, 0}, /* ENABLE */
+ {"reset", NULL, 0}, /* RESET */
+ {"disable", NULL, 0}, /* DISABLE */
+ {"speed", &speed, 0}, /* SPEED */
+ {"espeed", &espeed, 0}, /* EXTENDED SPEED */
+ {"fdr10", &fdr10, 0}, /* FDR10 SPEED */
+ {"width", &width, 0}, /* WIDTH */
+ {"down", NULL, 0}, /* DOWN */
+ {"arm", NULL, 0}, /* ARM */
+ {"active", NULL, 0}, /* ACTIVE */
+ {"vls", &vls, 0}, /* VLS */
+ {"mtu", &mtu, 0}, /* MTU */
+ {"lid", &lid, 0}, /* LID */
+ {"smlid", &smlid, 0}, /* SMLID */
+ {"lmc", &lmc, 0}, /* LMC */
+ {"mkey", &mkey, 0}, /* MKEY */
+ {"mkeylease", &mkeylease, 0}, /* MKEY LEASE */
+ {"mkeyprot", &mkeyprot, 0}, /* MKEY PROTECT BITS */
+ {"on", NULL, 0}, /* ON */
+ {"off", NULL, 0}, /* OFF */
+};
+
+#define NPORT_ARGS (sizeof(port_args) / sizeof(port_args[0]))
+
+/*******************************************/
+
+/*
+ * Return 1 if node is a switch, else zero.
+ */
+static int get_node_info(ib_portid_t * dest, uint8_t * data)
+{
+ int node_type;
+
+ if (!smp_query_via(data, dest, IB_ATTR_NODE_INFO, 0, 0, srcport))
+ IBEXIT("smp query nodeinfo failed");
+
+ node_type = mad_get_field(data, 0, IB_NODE_TYPE_F);
+ if (node_type == IB_NODE_SWITCH) /* Switch NodeType ? */
+ return 1;
+ else
+ return 0;
+}
+
+static int get_port_info(ib_portid_t * dest, uint8_t * data, int portnum,
+ int is_switch)
+{
+ uint8_t smp[IB_SMP_DATA_SIZE];
+ uint8_t *info;
+ int cap_mask;
+
+ if (is_switch) {
+ if (!smp_query_via(smp, dest, IB_ATTR_PORT_INFO, 0, 0, srcport))
+ IBEXIT("smp query port 0 portinfo failed");
+ info = smp;
+ } else
+ info = data;
+
+ if (!smp_query_via(data, dest, IB_ATTR_PORT_INFO, portnum, 0, srcport))
+ IBEXIT("smp query portinfo failed");
+ cap_mask = mad_get_field(info, 0, IB_PORT_CAPMASK_F);
+ return (cap_mask & CL_NTOH32(IB_PORT_CAP_HAS_EXT_SPEEDS));
+}
+
+static void show_port_info(ib_portid_t * dest, uint8_t * data, int portnum,
+ int espeed_cap, int is_switch)
+{
+ char buf[2300];
+ char val[64];
+
+ mad_dump_portstates(buf, sizeof buf, data, sizeof *data);
+ mad_decode_field(data, IB_PORT_LID_F, val);
+ mad_dump_field(IB_PORT_LID_F, buf + strlen(buf),
+ sizeof buf - strlen(buf), val);
+ sprintf(buf + strlen(buf), "%s", "\n");
+ mad_decode_field(data, IB_PORT_SMLID_F, val);
+ mad_dump_field(IB_PORT_SMLID_F, buf + strlen(buf),
+ sizeof buf - strlen(buf), val);
+ sprintf(buf + strlen(buf), "%s", "\n");
+ mad_decode_field(data, IB_PORT_LMC_F, val);
+ mad_dump_field(IB_PORT_LMC_F, buf + strlen(buf),
+ sizeof buf - strlen(buf), val);
+ sprintf(buf + strlen(buf), "%s", "\n");
+ mad_decode_field(data, IB_PORT_LINK_WIDTH_SUPPORTED_F, val);
+ mad_dump_field(IB_PORT_LINK_WIDTH_SUPPORTED_F, buf + strlen(buf),
+ sizeof buf - strlen(buf), val);
+ sprintf(buf + strlen(buf), "%s", "\n");
+ mad_decode_field(data, IB_PORT_LINK_WIDTH_ENABLED_F, val);
+ mad_dump_field(IB_PORT_LINK_WIDTH_ENABLED_F, buf + strlen(buf),
+ sizeof buf - strlen(buf), val);
+ sprintf(buf + strlen(buf), "%s", "\n");
+ mad_decode_field(data, IB_PORT_LINK_WIDTH_ACTIVE_F, val);
+ mad_dump_field(IB_PORT_LINK_WIDTH_ACTIVE_F, buf + strlen(buf),
+ sizeof buf - strlen(buf), val);
+ sprintf(buf + strlen(buf), "%s", "\n");
+ mad_decode_field(data, IB_PORT_LINK_SPEED_SUPPORTED_F, val);
+ mad_dump_field(IB_PORT_LINK_SPEED_SUPPORTED_F, buf + strlen(buf),
+ sizeof buf - strlen(buf), val);
+ sprintf(buf + strlen(buf), "%s", "\n");
+ mad_decode_field(data, IB_PORT_LINK_SPEED_ENABLED_F, val);
+ mad_dump_field(IB_PORT_LINK_SPEED_ENABLED_F, buf + strlen(buf),
+ sizeof buf - strlen(buf), val);
+ sprintf(buf + strlen(buf), "%s", "\n");
+ mad_decode_field(data, IB_PORT_LINK_SPEED_ACTIVE_F, val);
+ mad_dump_field(IB_PORT_LINK_SPEED_ACTIVE_F, buf + strlen(buf),
+ sizeof buf - strlen(buf), val);
+ sprintf(buf + strlen(buf), "%s", "\n");
+ if (espeed_cap) {
+ mad_decode_field(data, IB_PORT_LINK_SPEED_EXT_SUPPORTED_F, val);
+ mad_dump_field(IB_PORT_LINK_SPEED_EXT_SUPPORTED_F,
+ buf + strlen(buf), sizeof buf - strlen(buf),
+ val);
+ sprintf(buf + strlen(buf), "%s", "\n");
+ mad_decode_field(data, IB_PORT_LINK_SPEED_EXT_ENABLED_F, val);
+ mad_dump_field(IB_PORT_LINK_SPEED_EXT_ENABLED_F,
+ buf + strlen(buf), sizeof buf - strlen(buf),
+ val);
+ sprintf(buf + strlen(buf), "%s", "\n");
+ mad_decode_field(data, IB_PORT_LINK_SPEED_EXT_ACTIVE_F, val);
+ mad_dump_field(IB_PORT_LINK_SPEED_EXT_ACTIVE_F,
+ buf + strlen(buf), sizeof buf - strlen(buf),
+ val);
+ sprintf(buf + strlen(buf), "%s", "\n");
+ }
+ if (!is_switch || portnum == 0) {
+ if (show_keys) {
+ mad_decode_field(data, IB_PORT_MKEY_F, val);
+ mad_dump_field(IB_PORT_MKEY_F, buf + strlen(buf),
+ sizeof buf - strlen(buf), val);
+ } else
+ snprint_field(buf+strlen(buf), sizeof(buf)-strlen(buf),
+ IB_PORT_MKEY_F, 32, NOT_DISPLAYED_STR);
+ sprintf(buf+strlen(buf), "%s", "\n");
+ mad_decode_field(data, IB_PORT_MKEY_LEASE_F, val);
+ mad_dump_field(IB_PORT_MKEY_LEASE_F, buf + strlen(buf),
+ sizeof buf - strlen(buf), val);
+ sprintf(buf+strlen(buf), "%s", "\n");
+ mad_decode_field(data, IB_PORT_MKEY_PROT_BITS_F, val);
+ mad_dump_field(IB_PORT_MKEY_PROT_BITS_F, buf + strlen(buf),
+ sizeof buf - strlen(buf), val);
+ sprintf(buf+strlen(buf), "%s", "\n");
+ }
+
+ printf("# Port info: %s port %d\n%s", portid2str(dest), portnum, buf);
+}
+
+static void set_port_info(ib_portid_t * dest, uint8_t * data, int portnum,
+ int espeed_cap, int is_switch)
+{
+ unsigned mod;
+
+ mod = portnum;
+ if (espeed_cap)
+ mod |= 1<<31;
+ if (!smp_set_via(data, dest, IB_ATTR_PORT_INFO, mod, 0, srcport))
+ IBEXIT("smp set portinfo failed");
+
+ printf("\nAfter PortInfo set:\n");
+ show_port_info(dest, data, portnum, espeed_cap, is_switch);
+}
+
+static void get_mlnx_ext_port_info(ib_portid_t * dest, uint8_t * data, int portnum)
+{
+ if (!smp_query_via(data, dest, IB_ATTR_MLNX_EXT_PORT_INFO,
+ portnum, 0, srcport))
+ IBEXIT("smp query ext portinfo failed");
+}
+
+static void show_mlnx_ext_port_info(ib_portid_t * dest, uint8_t * data, int portnum)
+{
+ char buf[256];
+
+ mad_dump_mlnx_ext_port_info(buf, sizeof buf, data, IB_SMP_DATA_SIZE);
+
+ printf("# MLNX ext Port info: %s port %d\n%s", portid2str(dest),
+ portnum, buf);
+}
+
+static void set_mlnx_ext_port_info(ib_portid_t * dest, uint8_t * data, int portnum)
+{
+ if (!smp_set_via(data, dest, IB_ATTR_MLNX_EXT_PORT_INFO,
+ portnum, 0, srcport))
+ IBEXIT("smp set MLNX ext portinfo failed");
+
+ printf("\nAfter MLNXExtendedPortInfo set:\n");
+ show_mlnx_ext_port_info(dest, data, portnum);
+}
+
+static int get_link_width(int lwe, int lws)
+{
+ if (lwe == 255)
+ return lws;
+ else
+ return lwe;
+}
+
+static int get_link_speed(int lse, int lss)
+{
+ if (lse == 15)
+ return lss;
+ else
+ return lse;
+}
+
+static int get_link_speed_ext(int lsee, int lses)
+{
+ if (lsee == 31)
+ return lses;
+ else
+ return lsee;
+}
+
+static void validate_width(int width, int peerwidth, int lwa)
+{
+ if ((width & peerwidth & 0x8)) {
+ if (lwa != 8)
+ IBWARN
+ ("Peer ports operating at active width %d rather than 8 (12x)",
+ lwa);
+ } else if ((width & peerwidth & 0x4)) {
+ if (lwa != 4)
+ IBWARN
+ ("Peer ports operating at active width %d rather than 4 (8x)",
+ lwa);
+ } else if ((width & peerwidth & 0x2)) {
+ if (lwa != 2)
+ IBWARN
+ ("Peer ports operating at active width %d rather than 2 (4x)",
+ lwa);
+ } else if ((width & peerwidth & 0x10)) {
+ if (lwa != 16)
+ IBWARN
+ ("Peer ports operating at active width %d rather than 16 (2x)",
+ lwa);
+ } else if ((width & peerwidth & 0x1)) {
+ if (lwa != 1)
+ IBWARN
+ ("Peer ports operating at active width %d rather than 1 (1x)",
+ lwa);
+ }
+}
+
+static void validate_speed(int speed, int peerspeed, int lsa)
+{
+ if ((speed & peerspeed & 0x4)) {
+ if (lsa != 4)
+ IBWARN
+ ("Peer ports operating at active speed %d rather than 4 (10.0 Gbps)",
+ lsa);
+ } else if ((speed & peerspeed & 0x2)) {
+ if (lsa != 2)
+ IBWARN
+ ("Peer ports operating at active speed %d rather than 2 (5.0 Gbps)",
+ lsa);
+ } else if ((speed & peerspeed & 0x1)) {
+ if (lsa != 1)
+ IBWARN
+ ("Peer ports operating at active speed %d rather than 1 (2.5 Gbps)",
+ lsa);
+ }
+}
+
+static void validate_extended_speed(int espeed, int peerespeed, int lsea)
+{
+ if ((espeed & peerespeed & 0x2)) {
+ if (lsea != 2)
+ IBWARN
+ ("Peer ports operating at active extended speed %d rather than 2 (25.78125 Gbps)",
+ lsea);
+ } else if ((espeed & peerespeed & 0x1)) {
+ if (lsea != 1)
+ IBWARN
+ ("Peer ports operating at active extended speed %d rather than 1 (14.0625 Gbps)",
+ lsea);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ int mgmt_classes[3] =
+ { IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS };
+ ib_portid_t portid = { 0 };
+ int port_op = -1;
+ int is_switch, is_peer_switch, espeed_cap, peer_espeed_cap;
+ int state, physstate, lwe, lws, lwa, lse, lss, lsa, lsee, lses, lsea,
+ fdr10s, fdr10e, fdr10a;
+ int peerlocalportnum, peerlwe, peerlws, peerlwa, peerlse, peerlss,
+ peerlsa, peerlsee, peerlses, peerlsea, peerfdr10s, peerfdr10e,
+ peerfdr10a;
+ int peerwidth, peerspeed, peerespeed;
+ uint8_t data[IB_SMP_DATA_SIZE] = { 0 };
+ uint8_t data2[IB_SMP_DATA_SIZE] = { 0 };
+ ib_portid_t peerportid = { 0 };
+ int portnum = 0;
+ ib_portid_t selfportid = { 0 };
+ int selfport = 0;
+ int changed = 0;
+ int i;
+ uint32_t vendorid, rem_vendorid;
+ uint16_t devid, rem_devid;
+ uint64_t val;
+ char *endp;
+ char usage_args[] = "<dest dr_path|lid|guid> <portnum> [<op>]\n"
+ "\nSupported ops: enable, disable, on, off, reset, speed, espeed, fdr10,\n"
+ "\twidth, query, down, arm, active, vls, mtu, lid, smlid, lmc,\n"
+ "\tmkey, mkeylease, mkeyprot\n";
+ const char *usage_examples[] = {
+ "3 1 disable\t\t\t# by lid",
+ "-G 0x2C9000100D051 1 enable\t# by guid",
+ "-D 0 1\t\t\t# (query) by direct route",
+ "3 1 reset\t\t\t# by lid",
+ "3 1 speed 1\t\t\t# by lid",
+ "3 1 width 1\t\t\t# by lid",
+ "-D 0 1 lid 0x1234 arm\t\t# by direct route",
+ NULL
+ };
+
+ ibdiag_process_opts(argc, argv, NULL, NULL, NULL, NULL,
+ usage_args, usage_examples);
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 2)
+ ibdiag_show_usage();
+
+ srcport = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 3);
+ if (!srcport)
+ IBEXIT("Failed to open '%s' port '%d'", ibd_ca, ibd_ca_port);
+
+ smp_mkey_set(srcport, ibd_mkey);
+
+ if (resolve_portid_str(ibd_ca, ibd_ca_port, &portid, argv[0],
+ ibd_dest_type, ibd_sm_id, srcport) < 0)
+ IBEXIT("can't resolve destination port %s", argv[0]);
+
+ if (argc > 1)
+ portnum = strtol(argv[1], 0, 0);
+
+ for (i = 2; i < argc; i++) {
+ int j;
+
+ for (j = 0; j < NPORT_ARGS; j++) {
+ if (strcmp(argv[i], port_args[j].name))
+ continue;
+ port_args[j].set = 1;
+ if (!port_args[j].val) {
+ if (port_op >= 0)
+ IBEXIT("%s only one of: ",
+ "query, enable, disable, "
+ "reset, down, arm, active, "
+ "can be specified",
+ port_args[j].name);
+ port_op = j;
+ break;
+ }
+ if (++i >= argc)
+ IBEXIT("%s requires an additional parameter",
+ port_args[j].name);
+ val = strtoull(argv[i], 0, 0);
+ switch (j) {
+ case SPEED:
+ if (val > 15)
+ IBEXIT("invalid speed value %ld", val);
+ break;
+ case ESPEED:
+ if (val > 31)
+ IBEXIT("invalid extended speed value %ld", val);
+ break;
+ case FDR10SPEED:
+ if (val > 1)
+ IBEXIT("invalid fdr10 speed value %ld", val);
+ break;
+ case WIDTH:
+ if ((val > 31 && val != 255))
+ IBEXIT("invalid width value %ld", val);
+ break;
+ case VLS:
+ if (val == 0 || val > 5)
+ IBEXIT("invalid vls value %ld", val);
+ break;
+ case MTU:
+ if (val == 0 || val > 5)
+ IBEXIT("invalid mtu value %ld", val);
+ break;
+ case LID:
+ if (val == 0 || val >= 0xC000)
+ IBEXIT("invalid lid value 0x%lx", val);
+ break;
+ case SMLID:
+ if (val == 0 || val >= 0xC000)
+ IBEXIT("invalid smlid value 0x%lx",
+ val);
+ break;
+ case LMC:
+ if (val > 7)
+ IBEXIT("invalid lmc value %ld", val);
+ break;
+ case MKEY:
+ errno = 0;
+ val = strtoull(argv[i], &endp, 0);
+ if (errno || *endp != '\0') {
+ errno = 0;
+ val = strtoull(getpass("New M_Key: "),
+ &endp, 0);
+ if (errno || *endp != '\0') {
+ IBEXIT("Bad new M_Key\n");
+ }
+ }
+ /* All 64-bit values are legal */
+ break;
+ case MKEYLEASE:
+ if (val > 0xFFFF)
+ IBEXIT("invalid mkey lease time %ld", val);
+ break;
+ case MKEYPROT:
+ if (val > 3)
+ IBEXIT("invalid mkey protection bit setting %ld", val);
+ }
+ *port_args[j].val = val;
+ changed = 1;
+ break;
+ }
+ if (j == NPORT_ARGS)
+ IBEXIT("invalid operation: %s", argv[i]);
+ }
+ if (port_op < 0)
+ port_op = QUERY;
+
+ is_switch = get_node_info(&portid, data);
+ vendorid = (uint32_t) mad_get_field(data, 0, IB_NODE_VENDORID_F);
+ devid = (uint16_t) mad_get_field(data, 0, IB_NODE_DEVID_F);
+
+ if ((port_args[MKEY].set || port_args[MKEYLEASE].set ||
+ port_args[MKEYPROT].set) && is_switch && portnum != 0)
+ IBEXIT("Can't set M_Key fields on switch port != 0");
+
+ if (port_op != QUERY || changed)
+ printf("Initial %s PortInfo:\n", is_switch ? "Switch" : "CA/RT");
+ else
+ printf("%s PortInfo:\n", is_switch ? "Switch" : "CA/RT");
+ espeed_cap = get_port_info(&portid, data, portnum, is_switch);
+ show_port_info(&portid, data, portnum, espeed_cap, is_switch);
+ if (is_mlnx_ext_port_info_supported(vendorid, devid)) {
+ get_mlnx_ext_port_info(&portid, data2, portnum);
+ show_mlnx_ext_port_info(&portid, data2, portnum);
+ }
+
+ if (port_op != QUERY || changed) {
+ /*
+ * If we aren't setting the LID and the LID is the default,
+ * the SMA command will fail due to an invalid LID.
+ * Set it to something unlikely but valid.
+ */
+ physstate = mad_get_field(data, 0, IB_PORT_PHYS_STATE_F);
+
+ val = mad_get_field(data, 0, IB_PORT_LID_F);
+ if (!port_args[LID].set && (!val || val == 0xFFFF))
+ mad_set_field(data, 0, IB_PORT_LID_F, 0x1234);
+ val = mad_get_field(data, 0, IB_PORT_SMLID_F);
+ if (!port_args[SMLID].set && (!val || val == 0xFFFF))
+ mad_set_field(data, 0, IB_PORT_SMLID_F, 0x1234);
+ mad_set_field(data, 0, IB_PORT_STATE_F, 0); /* NOP */
+ mad_set_field(data, 0, IB_PORT_PHYS_STATE_F, 0); /* NOP */
+
+ switch (port_op) {
+ case ON:
+ /* Enable only if state is Disable */
+ if(physstate != 3) {
+ printf("Port is already in enable state\n");
+ goto close_port;
+ }
+ case ENABLE:
+ case RESET:
+ /* Polling */
+ mad_set_field(data, 0, IB_PORT_PHYS_STATE_F, 2);
+ break;
+ case OFF:
+ case DISABLE:
+ printf("Disable may be irreversible\n");
+ mad_set_field(data, 0, IB_PORT_PHYS_STATE_F, 3);
+ break;
+ case DOWN:
+ mad_set_field(data, 0, IB_PORT_STATE_F, 1);
+ break;
+ case ARM:
+ mad_set_field(data, 0, IB_PORT_STATE_F, 3);
+ break;
+ case ACTIVE:
+ mad_set_field(data, 0, IB_PORT_STATE_F, 4);
+ break;
+ }
+
+ /* always set enabled speeds/width - defaults to NOP */
+ mad_set_field(data, 0, IB_PORT_LINK_SPEED_ENABLED_F, speed);
+ mad_set_field(data, 0, IB_PORT_LINK_SPEED_EXT_ENABLED_F, espeed);
+ mad_set_field(data, 0, IB_PORT_LINK_WIDTH_ENABLED_F, width);
+
+ if (port_args[VLS].set)
+ mad_set_field(data, 0, IB_PORT_OPER_VLS_F, vls);
+ if (port_args[MTU].set)
+ mad_set_field(data, 0, IB_PORT_NEIGHBOR_MTU_F, mtu);
+ if (port_args[LID].set)
+ mad_set_field(data, 0, IB_PORT_LID_F, lid);
+ if (port_args[SMLID].set)
+ mad_set_field(data, 0, IB_PORT_SMLID_F, smlid);
+ if (port_args[LMC].set)
+ mad_set_field(data, 0, IB_PORT_LMC_F, lmc);
+
+ if (port_args[FDR10SPEED].set) {
+ mad_set_field(data2, 0,
+ IB_MLNX_EXT_PORT_STATE_CHG_ENABLE_F,
+ FDR10);
+ mad_set_field(data2, 0,
+ IB_MLNX_EXT_PORT_LINK_SPEED_ENABLED_F,
+ fdr10);
+ set_mlnx_ext_port_info(&portid, data2, portnum);
+ }
+
+ if (port_args[MKEY].set)
+ mad_set_field64(data, 0, IB_PORT_MKEY_F, mkey);
+ if (port_args[MKEYLEASE].set)
+ mad_set_field(data, 0, IB_PORT_MKEY_LEASE_F,
+ mkeylease);
+ if (port_args[MKEYPROT].set)
+ mad_set_field(data, 0, IB_PORT_MKEY_PROT_BITS_F,
+ mkeyprot);
+
+ set_port_info(&portid, data, portnum, espeed_cap, is_switch);
+
+ } else if (is_switch && portnum) {
+ /* Now, make sure PortState is Active */
+ /* Or is PortPhysicalState LinkUp sufficient ? */
+ mad_decode_field(data, IB_PORT_STATE_F, &state);
+ mad_decode_field(data, IB_PORT_PHYS_STATE_F, &physstate);
+ if (state == 4) { /* Active */
+ mad_decode_field(data, IB_PORT_LINK_WIDTH_ENABLED_F,
+ &lwe);
+ mad_decode_field(data, IB_PORT_LINK_WIDTH_SUPPORTED_F,
+ &lws);
+ mad_decode_field(data, IB_PORT_LINK_WIDTH_ACTIVE_F,
+ &lwa);
+ mad_decode_field(data, IB_PORT_LINK_SPEED_SUPPORTED_F,
+ &lss);
+ mad_decode_field(data, IB_PORT_LINK_SPEED_ACTIVE_F,
+ &lsa);
+ mad_decode_field(data, IB_PORT_LINK_SPEED_ENABLED_F,
+ &lse);
+ mad_decode_field(data2,
+ IB_MLNX_EXT_PORT_LINK_SPEED_SUPPORTED_F,
+ &fdr10s);
+ mad_decode_field(data2,
+ IB_MLNX_EXT_PORT_LINK_SPEED_ENABLED_F,
+ &fdr10e);
+ mad_decode_field(data2,
+ IB_MLNX_EXT_PORT_LINK_SPEED_ACTIVE_F,
+ &fdr10a);
+ if (espeed_cap) {
+ mad_decode_field(data,
+ IB_PORT_LINK_SPEED_EXT_SUPPORTED_F,
+ &lses);
+ mad_decode_field(data,
+ IB_PORT_LINK_SPEED_EXT_ACTIVE_F,
+ &lsea);
+ mad_decode_field(data,
+ IB_PORT_LINK_SPEED_EXT_ENABLED_F,
+ &lsee);
+ }
+
+ /* Setup portid for peer port */
+ memcpy(&peerportid, &portid, sizeof(peerportid));
+ if (portid.lid == 0) {
+ peerportid.drpath.cnt++;
+ if (peerportid.drpath.cnt == IB_SUBNET_PATH_HOPS_MAX) {
+ IBEXIT("Too many hops");
+ }
+ } else {
+ peerportid.drpath.cnt = 1;
+
+ /* Set DrSLID to local lid */
+ if (resolve_self(ibd_ca, ibd_ca_port, &selfportid,
+ &selfport, 0) < 0)
+ IBEXIT("could not resolve self");
+ peerportid.drpath.drslid = (uint16_t) selfportid.lid;
+ peerportid.drpath.drdlid = 0xffff;
+ }
+ peerportid.drpath.p[peerportid.drpath.cnt] = (uint8_t) portnum;
+
+ /* Get peer port NodeInfo to obtain peer port number */
+ is_peer_switch = get_node_info(&peerportid, data);
+ rem_vendorid = (uint32_t) mad_get_field(data, 0, IB_NODE_VENDORID_F);
+ rem_devid = (uint16_t) mad_get_field(data, 0, IB_NODE_DEVID_F);
+
+ mad_decode_field(data, IB_NODE_LOCAL_PORT_F,
+ &peerlocalportnum);
+
+ printf("Peer PortInfo:\n");
+ /* Get peer port characteristics */
+ peer_espeed_cap = get_port_info(&peerportid, data,
+ peerlocalportnum,
+ is_peer_switch);
+ if (is_mlnx_ext_port_info_supported(rem_vendorid, rem_devid))
+ get_mlnx_ext_port_info(&peerportid, data2,
+ peerlocalportnum);
+ show_port_info(&peerportid, data, peerlocalportnum,
+ peer_espeed_cap, is_peer_switch);
+ if (is_mlnx_ext_port_info_supported(rem_vendorid, rem_devid))
+ show_mlnx_ext_port_info(&peerportid, data2,
+ peerlocalportnum);
+
+ mad_decode_field(data, IB_PORT_LINK_WIDTH_ENABLED_F,
+ &peerlwe);
+ mad_decode_field(data, IB_PORT_LINK_WIDTH_SUPPORTED_F,
+ &peerlws);
+ mad_decode_field(data, IB_PORT_LINK_WIDTH_ACTIVE_F,
+ &peerlwa);
+ mad_decode_field(data, IB_PORT_LINK_SPEED_SUPPORTED_F,
+ &peerlss);
+ mad_decode_field(data, IB_PORT_LINK_SPEED_ACTIVE_F,
+ &peerlsa);
+ mad_decode_field(data, IB_PORT_LINK_SPEED_ENABLED_F,
+ &peerlse);
+ mad_decode_field(data2,
+ IB_MLNX_EXT_PORT_LINK_SPEED_SUPPORTED_F,
+ &peerfdr10s);
+ mad_decode_field(data2,
+ IB_MLNX_EXT_PORT_LINK_SPEED_ENABLED_F,
+ &peerfdr10e);
+ mad_decode_field(data2,
+ IB_MLNX_EXT_PORT_LINK_SPEED_ACTIVE_F,
+ &peerfdr10a);
+ if (peer_espeed_cap) {
+ mad_decode_field(data,
+ IB_PORT_LINK_SPEED_EXT_SUPPORTED_F,
+ &peerlses);
+ mad_decode_field(data,
+ IB_PORT_LINK_SPEED_EXT_ACTIVE_F,
+ &peerlsea);
+ mad_decode_field(data,
+ IB_PORT_LINK_SPEED_EXT_ENABLED_F,
+ &peerlsee);
+ }
+
+ /* Now validate peer port characteristics */
+ /* Examine Link Width */
+ width = get_link_width(lwe, lws);
+ peerwidth = get_link_width(peerlwe, peerlws);
+ validate_width(width, peerwidth, lwa);
+
+ /* Examine Link Speeds */
+ speed = get_link_speed(lse, lss);
+ peerspeed = get_link_speed(peerlse, peerlss);
+ validate_speed(speed, peerspeed, lsa);
+
+ if (espeed_cap && peer_espeed_cap) {
+ espeed = get_link_speed_ext(lsee, lses);
+ peerespeed = get_link_speed_ext(peerlsee,
+ peerlses);
+ validate_extended_speed(espeed, peerespeed,
+ lsea);
+ } else {
+ if (fdr10e & FDR10 && peerfdr10e & FDR10) {
+ if (!(fdr10a & FDR10))
+ IBWARN("Peer ports operating at active speed %d rather than FDR10", lsa);
+ }
+ }
+ }
+ }
+
+close_port:
+ mad_rpc_close_port(srcport);
+ exit(0);
+}
diff --git a/contrib/ofed/infiniband-diags/src/ibqueryerrors.c b/contrib/ofed/infiniband-diags/src/ibqueryerrors.c
new file mode 100644
index 000000000000..2329f9147718
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/src/ibqueryerrors.c
@@ -0,0 +1,1126 @@
+/*
+ * Copyright (c) 2004-2009 Voltaire Inc. All rights reserved.
+ * Copyright (c) 2007 Xsigo Systems Inc. All rights reserved.
+ * Copyright (c) 2008 Lawrence Livermore National Lab. All rights reserved.
+ * Copyright (c) 2009 HNR Consulting. All rights reserved.
+ * Copyright (c) 2010,2011 Mellanox Technologies LTD. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <time.h>
+#include <string.h>
+#include <getopt.h>
+#include <errno.h>
+#include <inttypes.h>
+
+#include <complib/cl_nodenamemap.h>
+#include <infiniband/ibnetdisc.h>
+#include <infiniband/mad.h>
+
+#include "ibdiag_common.h"
+#include "ibdiag_sa.h"
+
+struct ibmad_port *ibmad_port;
+static char *node_name_map_file = NULL;
+static nn_map_t *node_name_map = NULL;
+static char *load_cache_file = NULL;
+static uint16_t lid2sl_table[sizeof(uint8_t) * 1024 * 48] = { 0 };
+static int obtain_sl = 1;
+
+int data_counters = 0;
+int data_counters_only = 0;
+int port_config = 0;
+uint64_t port_guid = 0;
+char *port_guid_str = NULL;
+#define SUP_MAX 64
+int sup_total = 0;
+enum MAD_FIELDS suppressed_fields[SUP_MAX];
+char *dr_path = NULL;
+uint8_t node_type_to_print = 0;
+unsigned clear_errors = 0, clear_counts = 0, details = 0;
+
+#define PRINT_SWITCH 0x1
+#define PRINT_CA 0x2
+#define PRINT_ROUTER 0x4
+#define PRINT_ALL 0xFF /* all nodes default flag */
+
+#define DEFAULT_HALF_WORLD_PR_TIMEOUT (3000)
+
+struct {
+ int nodes_checked;
+ int bad_nodes;
+ int ports_checked;
+ int bad_ports;
+ int pma_query_failures;
+} summary = { 0 };
+
+#define DEF_THRES_FILE IBDIAG_CONFIG_PATH"/error_thresholds"
+static char *threshold_file = DEF_THRES_FILE;
+
+/* define a "packet" with threshold values in it */
+uint8_t thresholds[1204] = { 0 };
+char * threshold_str = "";
+
+static unsigned valid_gid(ib_gid_t * gid)
+{
+ ib_gid_t zero_gid;
+ memset(&zero_gid, 0, sizeof zero_gid);
+ return memcmp(&zero_gid, gid, sizeof(*gid));
+}
+
+static void set_thres(char *name, uint32_t val)
+{
+ int f;
+ int n;
+ char tmp[256];
+ for (f = IB_PC_FIRST_F; f <= IB_PC_LAST_F; f++) {
+ if (strcmp(name, mad_field_name(f)) == 0) {
+ mad_encode_field(thresholds, f, &val);
+ snprintf(tmp, 255, "[%s = %u]", name, val);
+ threshold_str = realloc(threshold_str,
+ strlen(threshold_str)+strlen(tmp)+1);
+ if (!threshold_str) {
+ fprintf(stderr, "Failed to allocate memory: "
+ "%s\n", strerror(errno));
+ exit(1);
+ }
+ n = strlen(threshold_str);
+ strcpy(threshold_str+n, tmp);
+ }
+ }
+}
+
+static void set_thresholds(char *threshold_file)
+{
+ char buf[1024];
+ int val = 0;
+ FILE *thresf = fopen(threshold_file, "r");
+ char *p_prefix, *p_last;
+ char *name;
+ char *val_str;
+ char str[64];
+
+ if (!thresf)
+ return;
+
+ snprintf(str, 63, "Thresholds: ");
+ threshold_str = malloc(strlen(str)+1);
+ if (!threshold_str) {
+ fprintf(stderr, "Failed to allocate memory: %s\n",
+ strerror(errno));
+ exit(1);
+ }
+ strcpy(threshold_str, str);
+ while (fgets(buf, sizeof buf, thresf) != NULL) {
+ p_prefix = strtok_r(buf, "\n", &p_last);
+ if (!p_prefix)
+ continue; /* ignore blank lines */
+
+ if (*p_prefix == '#')
+ continue; /* ignore comment lines */
+
+ name = strtok_r(p_prefix, "=", &p_last);
+ val_str = strtok_r(NULL, "\n", &p_last);
+
+ val = strtoul(val_str, NULL, 0);
+ set_thres(name, val);
+ }
+
+ fclose(thresf);
+}
+
+static int exceeds_threshold(int field, unsigned val)
+{
+ uint32_t thres = 0;
+ mad_decode_field(thresholds, field, &thres);
+ return (val > thres);
+}
+
+static void print_port_config(ibnd_node_t * node, int portnum)
+{
+ char width[64], speed[64], state[64], physstate[64];
+ char remote_str[256];
+ char link_str[256];
+ char width_msg[256];
+ char speed_msg[256];
+ char ext_port_str[256];
+ int iwidth, ispeed, fdr10, espeed, istate, iphystate, cap_mask;
+ uint8_t *info;
+
+ ibnd_port_t *port = node->ports[portnum];
+
+ if (!port)
+ return;
+
+ iwidth = mad_get_field(port->info, 0, IB_PORT_LINK_WIDTH_ACTIVE_F);
+ ispeed = mad_get_field(port->info, 0, IB_PORT_LINK_SPEED_ACTIVE_F);
+ fdr10 = mad_get_field(port->ext_info, 0,
+ IB_MLNX_EXT_PORT_LINK_SPEED_ACTIVE_F) & FDR10;
+
+ if (port->node->type == IB_NODE_SWITCH)
+ info = (uint8_t *)&port->node->ports[0]->info;
+ else
+ info = (uint8_t *)&port->info;
+ cap_mask = mad_get_field(info, 0, IB_PORT_CAPMASK_F);
+ if (cap_mask & CL_NTOH32(IB_PORT_CAP_HAS_EXT_SPEEDS))
+ espeed = mad_get_field(port->info, 0,
+ IB_PORT_LINK_SPEED_EXT_ACTIVE_F);
+ else
+ espeed = 0;
+ istate = mad_get_field(port->info, 0, IB_PORT_STATE_F);
+ iphystate = mad_get_field(port->info, 0, IB_PORT_PHYS_STATE_F);
+
+ remote_str[0] = '\0';
+ link_str[0] = '\0';
+ width_msg[0] = '\0';
+ speed_msg[0] = '\0';
+
+ /* C14-24.2.1 states that a down port allows for invalid data to be
+ * returned for all PortInfo components except PortState and
+ * PortPhysicalState */
+ if (istate != IB_LINK_DOWN) {
+ if (!espeed) {
+ if (fdr10)
+ sprintf(speed, "10.0 Gbps (FDR10)");
+ else
+ mad_dump_val(IB_PORT_LINK_SPEED_ACTIVE_F, speed,
+ 64, &ispeed);
+ } else
+ mad_dump_val(IB_PORT_LINK_SPEED_EXT_ACTIVE_F, speed,
+ 64, &espeed);
+
+ snprintf(link_str, 256, "(%3s %18s %6s/%8s)",
+ mad_dump_val(IB_PORT_LINK_WIDTH_ACTIVE_F, width, 64, &iwidth),
+ speed,
+ mad_dump_val(IB_PORT_STATE_F, state, 64, &istate),
+ mad_dump_val(IB_PORT_PHYS_STATE_F, physstate, 64, &iphystate));
+ } else {
+ snprintf(link_str, 256, "( %6s/%8s)",
+ mad_dump_val(IB_PORT_STATE_F, state, 64, &istate),
+ mad_dump_val(IB_PORT_PHYS_STATE_F, physstate, 64, &iphystate));
+ }
+
+ if (port->remoteport) {
+ char *rem_node_name = NULL;
+
+ if (port->remoteport->ext_portnum)
+ snprintf(ext_port_str, 256, "%d",
+ port->remoteport->ext_portnum);
+ else
+ ext_port_str[0] = '\0';
+
+ get_max_msg(width_msg, speed_msg, 256, port);
+
+ rem_node_name = remap_node_name(node_name_map,
+ port->remoteport->node->guid,
+ port->remoteport->node->
+ nodedesc);
+
+ snprintf(remote_str, 256,
+ "0x%016" PRIx64 " %6d %4d[%2s] \"%s\" (%s %s)\n",
+ port->remoteport->guid,
+ port->remoteport->base_lid ? port->remoteport->
+ base_lid : port->remoteport->node->smalid,
+ port->remoteport->portnum, ext_port_str, rem_node_name,
+ width_msg, speed_msg);
+
+ free(rem_node_name);
+ } else
+ snprintf(remote_str, 256, " [ ] \"\" ( )\n");
+
+ if (port->ext_portnum)
+ snprintf(ext_port_str, 256, "%d", port->ext_portnum);
+ else
+ ext_port_str[0] = '\0';
+
+ if (node->type == IB_NODE_SWITCH)
+ printf(" Link info: %6d", node->smalid);
+ else
+ printf(" Link info: %6d", port->base_lid);
+
+ printf("%4d[%2s] ==%s==> %s",
+ port->portnum, ext_port_str, link_str, remote_str);
+}
+
+static int suppress(enum MAD_FIELDS field)
+{
+ int i = 0;
+ for (i = 0; i < sup_total; i++)
+ if (field == suppressed_fields[i])
+ return 1;
+ return 0;
+}
+
+static void report_suppressed(void)
+{
+ int i = 0;
+ printf("## Suppressed:");
+ for (i = 0; i < sup_total; i++)
+ printf(" %s", mad_field_name(suppressed_fields[i]));
+ printf("\n");
+}
+
+static int print_summary(void)
+{
+ printf("\n## Summary: %d nodes checked, %d bad nodes found\n",
+ summary.nodes_checked, summary.bad_nodes);
+ printf("## %d ports checked, %d ports have errors beyond threshold\n",
+ summary.ports_checked, summary.bad_ports);
+ printf("## %s\n", threshold_str);
+ if (summary.pma_query_failures)
+ printf("## %d PMA query failures\n", summary.pma_query_failures);
+ report_suppressed();
+ return (summary.bad_ports);
+}
+
+static void insert_lid2sl_table(struct sa_query_result *r)
+{
+ unsigned int i;
+ for (i = 0; i < r->result_cnt; i++) {
+ ib_path_rec_t *p_pr = (ib_path_rec_t *)sa_get_query_rec(r->p_result_madw, i);
+ lid2sl_table[cl_ntoh16(p_pr->dlid)] = ib_path_rec_sl(p_pr);
+ }
+}
+
+static int path_record_query(ib_gid_t sgid,uint64_t dguid)
+{
+ ib_path_rec_t pr;
+ ib_net64_t comp_mask = 0;
+ uint8_t reversible = 0;
+ struct sa_handle * h;
+
+ if (!(h = sa_get_handle()))
+ return -1;
+
+ ibd_timeout = DEFAULT_HALF_WORLD_PR_TIMEOUT;
+ memset(&pr, 0, sizeof(pr));
+
+ CHECK_AND_SET_GID(sgid, pr.sgid, PR, SGID);
+ if(dguid) {
+ mad_encode_field(sgid.raw, IB_GID_GUID_F, &dguid);
+ CHECK_AND_SET_GID(sgid, pr.dgid, PR, DGID);
+ }
+
+ CHECK_AND_SET_VAL(1, 8, -1, pr.num_path, PR, NUMBPATH);/*to get only one PathRecord for each source and destination pair*/
+ CHECK_AND_SET_VAL(1, 8, -1, reversible, PR, REVERSIBLE);/*for a reversible path*/
+ pr.num_path |= reversible << 7;
+ struct sa_query_result result;
+ int ret = sa_query(h, IB_MAD_METHOD_GET_TABLE,
+ (uint16_t)IB_SA_ATTR_PATHRECORD,0,cl_ntoh64(comp_mask),ibd_sakey,
+ &pr, sizeof(pr), &result);
+ if (ret) {
+ sa_free_handle(h);
+ fprintf(stderr, "Query SA failed: %s; sa call path_query failed\n", strerror(ret));
+ return ret;
+ }
+ if (result.status != IB_SA_MAD_STATUS_SUCCESS) {
+ sa_report_err(result.status);
+ ret = EIO;
+ goto Exit;
+ }
+
+ insert_lid2sl_table(&result);
+Exit:
+ sa_free_handle(h);
+ sa_free_result_mad(&result);
+ return ret;
+}
+
+static int query_and_dump(char *buf, size_t size, ib_portid_t * portid,
+ char *node_name, int portnum,
+ const char *attr_name, uint16_t attr_id,
+ int start_field, int end_field)
+{
+ uint8_t pc[1024];
+ uint32_t val = 0;
+ int i, n;
+
+ memset(pc, 0, sizeof(pc));
+
+ if (!pma_query_via(pc, portid, portnum, ibd_timeout, attr_id,
+ ibmad_port)) {
+ IBWARN("%s query failed on %s, %s port %d", attr_name,
+ node_name, portid2str(portid), portnum);
+ summary.pma_query_failures++;
+ return 0;
+ }
+
+ for (n = 0, i = start_field; i < end_field; i++) {
+ mad_decode_field(pc, i, (void *)&val);
+ if (val)
+ n += snprintf(buf + n, size - n, " [%s == %u]",
+ mad_field_name(i), val);
+ }
+
+ return n;
+}
+
+
+static int print_results(ib_portid_t * portid, char *node_name,
+ ibnd_node_t * node, uint8_t * pc, int portnum,
+ int *header_printed, uint8_t *pce, uint16_t cap_mask)
+{
+ char buf[1024];
+ char *str = buf;
+ uint32_t val = 0;
+ int i, n;
+
+ for (n = 0, i = IB_PC_ERR_SYM_F; i <= IB_PC_VL15_DROPPED_F; i++) {
+ if (suppress(i))
+ continue;
+
+ /* this is not a counter, skip it */
+ if (i == IB_PC_COUNTER_SELECT2_F)
+ continue;
+
+ mad_decode_field(pc, i, (void *)&val);
+ if (exceeds_threshold(i, val)) {
+ n += snprintf(str + n, 1024 - n, " [%s == %u]",
+ mad_field_name(i), val);
+
+ /* If there are PortXmitDiscards, get details (if supported) */
+ if (i == IB_PC_XMT_DISCARDS_F && details) {
+ n += query_and_dump(str + n, sizeof(buf) - n, portid,
+ node_name, portnum,
+ "PortXmitDiscardDetails",
+ IB_GSI_PORT_XMIT_DISCARD_DETAILS,
+ IB_PC_RCV_LOCAL_PHY_ERR_F,
+ IB_PC_RCV_ERR_LAST_F);
+ /* If there are PortRcvErrors, get details (if supported) */
+ } else if (i == IB_PC_ERR_RCV_F && details) {
+ n += query_and_dump(str + n, sizeof(buf) - n, portid,
+ node_name, portnum,
+ "PortRcvErrorDetails",
+ IB_GSI_PORT_RCV_ERROR_DETAILS,
+ IB_PC_XMT_INACT_DISC_F,
+ IB_PC_XMT_DISC_LAST_F);
+ }
+ }
+ }
+
+ if (!suppress(IB_PC_XMT_WAIT_F)) {
+ mad_decode_field(pc, IB_PC_XMT_WAIT_F, (void *)&val);
+ if (exceeds_threshold(IB_PC_XMT_WAIT_F, val))
+ n += snprintf(str + n, 1024 - n, " [%s == %u]",
+ mad_field_name(IB_PC_XMT_WAIT_F), val);
+ }
+
+ /* if we found errors. */
+ if (n != 0) {
+ if (data_counters) {
+ uint8_t *pkt = pc;
+ int start_field = IB_PC_XMT_BYTES_F;
+ int end_field = IB_PC_RCV_PKTS_F;
+
+ if (pce) {
+ pkt = pce;
+ start_field = IB_PC_EXT_XMT_BYTES_F;
+ if (cap_mask & IB_PM_EXT_WIDTH_SUPPORTED)
+ end_field = IB_PC_EXT_RCV_MPKTS_F;
+ else
+ end_field = IB_PC_EXT_RCV_PKTS_F;
+ }
+
+ for (i = start_field; i <= end_field; i++) {
+ uint64_t val64 = 0;
+ float val = 0;
+ char *unit = "";
+ mad_decode_field(pkt, i, (void *)&val64);
+ if (val64) {
+ int data = 0;
+ if (i == IB_PC_EXT_XMT_BYTES_F ||
+ i == IB_PC_EXT_RCV_BYTES_F ||
+ i == IB_PC_XMT_BYTES_F ||
+ i == IB_PC_RCV_BYTES_F)
+ data = 1;
+ unit = conv_cnt_human_readable(val64,
+ &val, data);
+ n += snprintf(str + n, 1024 - n,
+ " [%s == %" PRIu64
+ " (%5.3f%s)]",
+ mad_field_name(i), val64, val,
+ unit);
+ }
+ }
+ }
+
+ if (!*header_printed) {
+ if (node->type == IB_NODE_SWITCH)
+ printf("Errors for 0x%" PRIx64 " \"%s\"\n",
+ node->ports[0]->guid, node_name);
+ else
+ printf("Errors for \"%s\"\n", node_name);
+ *header_printed = 1;
+ summary.bad_nodes++;
+ }
+
+ if (portnum == 0xFF) {
+ if (node->type == IB_NODE_SWITCH)
+ printf(" GUID 0x%" PRIx64 " port ALL:%s\n",
+ node->ports[0]->guid, str);
+ } else {
+ printf(" GUID 0x%" PRIx64 " port %d:%s\n",
+ node->ports[portnum]->guid, portnum, str);
+ if (port_config)
+ print_port_config(node, portnum);
+ summary.bad_ports++;
+ }
+ }
+ return (n);
+}
+
+static int query_cap_mask(ib_portid_t * portid, char *node_name, int portnum,
+ uint16_t * cap_mask)
+{
+ uint8_t pc[1024] = { 0 };
+ uint16_t rc_cap_mask;
+
+ portid->sl = lid2sl_table[portid->lid];
+
+ /* PerfMgt ClassPortInfo is a required attribute */
+ if (!pma_query_via(pc, portid, portnum, ibd_timeout, CLASS_PORT_INFO,
+ ibmad_port)) {
+ IBWARN("classportinfo query failed on %s, %s port %d",
+ node_name, portid2str(portid), portnum);
+ summary.pma_query_failures++;
+ return -1;
+ }
+
+ /* ClassPortInfo should be supported as part of libibmad */
+ memcpy(&rc_cap_mask, pc + 2, sizeof(rc_cap_mask)); /* CapabilityMask */
+
+ *cap_mask = rc_cap_mask;
+ return 0;
+}
+
+static int print_data_cnts(ib_portid_t * portid, uint16_t cap_mask,
+ char *node_name, ibnd_node_t * node, int portnum,
+ int *header_printed)
+{
+ uint8_t pc[1024];
+ int i;
+ int start_field = IB_PC_XMT_BYTES_F;
+ int end_field = IB_PC_RCV_PKTS_F;
+
+ memset(pc, 0, 1024);
+
+ portid->sl = lid2sl_table[portid->lid];
+
+ if (cap_mask & (IB_PM_EXT_WIDTH_SUPPORTED | IB_PM_EXT_WIDTH_NOIETF_SUP)) {
+ if (!pma_query_via(pc, portid, portnum, ibd_timeout,
+ IB_GSI_PORT_COUNTERS_EXT, ibmad_port)) {
+ IBWARN("IB_GSI_PORT_COUNTERS_EXT query failed on %s, %s port %d",
+ node_name, portid2str(portid), portnum);
+ summary.pma_query_failures++;
+ return (1);
+ }
+ start_field = IB_PC_EXT_XMT_BYTES_F;
+ if (cap_mask & IB_PM_EXT_WIDTH_SUPPORTED)
+ end_field = IB_PC_EXT_RCV_MPKTS_F;
+ else
+ end_field = IB_PC_EXT_RCV_PKTS_F;
+ } else {
+ if (!pma_query_via(pc, portid, portnum, ibd_timeout,
+ IB_GSI_PORT_COUNTERS, ibmad_port)) {
+ IBWARN("IB_GSI_PORT_COUNTERS query failed on %s, %s port %d",
+ node_name, portid2str(portid), portnum);
+ summary.pma_query_failures++;
+ return (1);
+ }
+ start_field = IB_PC_XMT_BYTES_F;
+ end_field = IB_PC_RCV_PKTS_F;
+ }
+
+ if (!*header_printed) {
+ printf("Data Counters for 0x%" PRIx64 " \"%s\"\n", node->guid,
+ node_name);
+ *header_printed = 1;
+ }
+
+ if (portnum == 0xFF)
+ printf(" GUID 0x%" PRIx64 " port ALL:", node->guid);
+ else
+ printf(" GUID 0x%" PRIx64 " port %d:",
+ node->guid, portnum);
+
+ for (i = start_field; i <= end_field; i++) {
+ uint64_t val64 = 0;
+ float val = 0;
+ char *unit = "";
+ int data = 0;
+ mad_decode_field(pc, i, (void *)&val64);
+ if (i == IB_PC_EXT_XMT_BYTES_F || i == IB_PC_EXT_RCV_BYTES_F ||
+ i == IB_PC_XMT_BYTES_F || i == IB_PC_RCV_BYTES_F)
+ data = 1;
+ unit = conv_cnt_human_readable(val64, &val, data);
+ printf(" [%s == %" PRIu64 " (%5.3f%s)]", mad_field_name(i),
+ val64, val, unit);
+ }
+ printf("\n");
+
+ if (portnum != 0xFF && port_config)
+ print_port_config(node, portnum);
+
+ return (0);
+}
+
+static int print_errors(ib_portid_t * portid, uint16_t cap_mask,
+ char *node_name, ibnd_node_t * node, int portnum,
+ int *header_printed)
+{
+ uint8_t pc[1024];
+ uint8_t pce[1024];
+ uint8_t *pc_ext = NULL;
+
+ memset(pc, 0, 1024);
+ memset(pce, 0, 1024);
+
+ portid->sl = lid2sl_table[portid->lid];
+
+ if (!pma_query_via(pc, portid, portnum, ibd_timeout,
+ IB_GSI_PORT_COUNTERS, ibmad_port)) {
+ IBWARN("IB_GSI_PORT_COUNTERS query failed on %s, %s port %d",
+ node_name, portid2str(portid), portnum);
+ summary.pma_query_failures++;
+ return (0);
+ }
+
+ if (cap_mask & (IB_PM_EXT_WIDTH_SUPPORTED | IB_PM_EXT_WIDTH_NOIETF_SUP)) {
+ if (!pma_query_via(pce, portid, portnum, ibd_timeout,
+ IB_GSI_PORT_COUNTERS_EXT, ibmad_port)) {
+ IBWARN("IB_GSI_PORT_COUNTERS_EXT query failed on %s, %s port %d",
+ node_name, portid2str(portid), portnum);
+ summary.pma_query_failures++;
+ return (0);
+ }
+ pc_ext = pce;
+ }
+
+ if (!(cap_mask & IB_PM_PC_XMIT_WAIT_SUP)) {
+ /* if PortCounters:PortXmitWait not supported clear this counter */
+ uint32_t foo = 0;
+ mad_encode_field(pc, IB_PC_XMT_WAIT_F, &foo);
+ }
+ return (print_results(portid, node_name, node, pc, portnum,
+ header_printed, pc_ext, cap_mask));
+}
+
+uint8_t *reset_pc_ext(void *rcvbuf, ib_portid_t * dest,
+ int port, unsigned mask, unsigned timeout,
+ const struct ibmad_port * srcport)
+{
+ ib_rpc_t rpc = { 0 };
+ int lid = dest->lid;
+
+ DEBUG("lid %u port %d mask 0x%x", lid, port, mask);
+
+ if (lid == -1) {
+ IBWARN("only lid routed is supported");
+ return NULL;
+ }
+
+ if (!mask)
+ mask = ~0;
+
+ rpc.mgtclass = IB_PERFORMANCE_CLASS;
+ rpc.method = IB_MAD_METHOD_SET;
+ rpc.attr.id = IB_GSI_PORT_COUNTERS_EXT;
+
+ memset(rcvbuf, 0, IB_MAD_SIZE);
+
+ /* Same for attribute IDs */
+ mad_set_field(rcvbuf, 0, IB_PC_EXT_PORT_SELECT_F, port);
+ mad_set_field(rcvbuf, 0, IB_PC_EXT_COUNTER_SELECT_F, mask);
+ rpc.attr.mod = 0;
+ rpc.timeout = timeout;
+ rpc.datasz = IB_PC_DATA_SZ;
+ rpc.dataoffs = IB_PC_DATA_OFFS;
+ if (!dest->qp)
+ dest->qp = 1;
+ if (!dest->qkey)
+ dest->qkey = IB_DEFAULT_QP1_QKEY;
+
+ return mad_rpc(srcport, &rpc, dest, rcvbuf, rcvbuf);
+}
+
+static void clear_port(ib_portid_t * portid, uint16_t cap_mask,
+ char *node_name, int port)
+{
+ uint8_t pc[1024] = { 0 };
+ /* bits defined in Table 228 PortCounters CounterSelect and
+ * CounterSelect2
+ */
+ uint32_t mask = 0;
+
+ if (clear_errors) {
+ mask |= 0xFFF;
+ if (cap_mask & IB_PM_PC_XMIT_WAIT_SUP)
+ mask |= 0x10000;
+ }
+ if (clear_counts)
+ mask |= 0xF000;
+
+ if (mask)
+ if (!performance_reset_via(pc, portid, port, mask, ibd_timeout,
+ IB_GSI_PORT_COUNTERS, ibmad_port))
+ fprintf(stderr, "Failed to reset errors %s port %d\n", node_name,
+ port);
+
+ if (clear_errors && details) {
+ memset(pc, 0, 1024);
+ performance_reset_via(pc, portid, port, 0xf, ibd_timeout,
+ IB_GSI_PORT_XMIT_DISCARD_DETAILS,
+ ibmad_port);
+ memset(pc, 0, 1024);
+ performance_reset_via(pc, portid, port, 0x3f, ibd_timeout,
+ IB_GSI_PORT_RCV_ERROR_DETAILS,
+ ibmad_port);
+ }
+
+ if (clear_counts &&
+ (cap_mask &
+ (IB_PM_EXT_WIDTH_SUPPORTED | IB_PM_EXT_WIDTH_NOIETF_SUP))) {
+ if (cap_mask & IB_PM_EXT_WIDTH_SUPPORTED)
+ mask = 0xFF;
+ else
+ mask = 0x0F;
+
+ if (!reset_pc_ext(pc, portid, port, mask, ibd_timeout,
+ ibmad_port))
+ fprintf(stderr, "Failed to reset extended data counters %s, "
+ "%s port %d\n", node_name, portid2str(portid),
+ port);
+ }
+}
+
+void print_node(ibnd_node_t * node, void *user_data)
+{
+ int header_printed = 0;
+ int p = 0;
+ int startport = 1;
+ int type = 0;
+ int all_port_sup = 0;
+ ib_portid_t portid = { 0 };
+ uint16_t cap_mask = 0;
+ char *node_name = NULL;
+
+ switch (node->type) {
+ case IB_NODE_SWITCH:
+ type = PRINT_SWITCH;
+ break;
+ case IB_NODE_CA:
+ type = PRINT_CA;
+ break;
+ case IB_NODE_ROUTER:
+ type = PRINT_ROUTER;
+ break;
+ }
+
+ if ((type & node_type_to_print) == 0)
+ return;
+
+ if (node->type == IB_NODE_SWITCH && node->smaenhsp0)
+ startport = 0;
+
+ node_name = remap_node_name(node_name_map, node->guid, node->nodedesc);
+
+ if (node->type == IB_NODE_SWITCH) {
+ ib_portid_set(&portid, node->smalid, 0, 0);
+ p = 0;
+ } else {
+ for (p = 1; p <= node->numports; p++) {
+ if (node->ports[p]) {
+ ib_portid_set(&portid,
+ node->ports[p]->base_lid,
+ 0, 0);
+ break;
+ }
+ }
+ }
+
+ if ((query_cap_mask(&portid, node_name, p, &cap_mask) == 0) &&
+ (cap_mask & IB_PM_ALL_PORT_SELECT))
+ all_port_sup = 1;
+
+ if (data_counters_only) {
+ for (p = startport; p <= node->numports; p++) {
+ if (node->ports[p]) {
+ if (node->type == IB_NODE_SWITCH)
+ ib_portid_set(&portid, node->smalid, 0, 0);
+ else
+ ib_portid_set(&portid, node->ports[p]->base_lid,
+ 0, 0);
+
+ print_data_cnts(&portid, cap_mask, node_name, node, p,
+ &header_printed);
+ summary.ports_checked++;
+ if (!all_port_sup)
+ clear_port(&portid, cap_mask, node_name, p);
+ }
+ }
+ } else {
+ if (all_port_sup)
+ if (!print_errors(&portid, cap_mask, node_name, node,
+ 0xFF, &header_printed)) {
+ summary.ports_checked += node->numports;
+ goto clear;
+ }
+
+ for (p = startport; p <= node->numports; p++) {
+ if (node->ports[p]) {
+ if (node->type == IB_NODE_SWITCH)
+ ib_portid_set(&portid, node->smalid, 0, 0);
+ else
+ ib_portid_set(&portid, node->ports[p]->base_lid,
+ 0, 0);
+
+ print_errors(&portid, cap_mask, node_name, node, p,
+ &header_printed);
+ summary.ports_checked++;
+ if (!all_port_sup)
+ clear_port(&portid, cap_mask, node_name, p);
+ }
+ }
+ }
+
+clear:
+ summary.nodes_checked++;
+ if (all_port_sup)
+ clear_port(&portid, cap_mask, node_name, 0xFF);
+
+ free(node_name);
+}
+
+static void add_suppressed(enum MAD_FIELDS field)
+{
+ if (sup_total >= SUP_MAX) {
+ IBWARN("Maximum (%d) fields have been suppressed; skipping %s",
+ sup_total, mad_field_name(field));
+ return;
+ }
+ suppressed_fields[sup_total++] = field;
+}
+
+static void calculate_suppressed_fields(char *str)
+{
+ enum MAD_FIELDS f;
+ char *val, *lasts = NULL;
+ char *tmp = strdup(str);
+
+ val = strtok_r(tmp, ",", &lasts);
+ while (val) {
+ for (f = IB_PC_FIRST_F; f <= IB_PC_LAST_F; f++)
+ if (strcmp(val, mad_field_name(f)) == 0)
+ add_suppressed(f);
+ val = strtok_r(NULL, ",", &lasts);
+ }
+
+ free(tmp);
+}
+
+static int process_opt(void *context, int ch, char *optarg)
+{
+ struct ibnd_config *cfg = context;
+ switch (ch) {
+ case 's':
+ calculate_suppressed_fields(optarg);
+ break;
+ case 'c':
+ /* Right now this is the only "common" error */
+ add_suppressed(IB_PC_ERR_SWITCH_REL_F);
+ break;
+ case 1:
+ node_name_map_file = strdup(optarg);
+ break;
+ case 2:
+ data_counters++;
+ break;
+ case 3:
+ node_type_to_print |= PRINT_SWITCH;
+ break;
+ case 4:
+ node_type_to_print |= PRINT_CA;
+ break;
+ case 5:
+ node_type_to_print |= PRINT_ROUTER;
+ break;
+ case 6:
+ details = 1;
+ break;
+ case 7:
+ load_cache_file = strdup(optarg);
+ break;
+ case 8:
+ threshold_file = strdup(optarg);
+ break;
+ case 9:
+ data_counters_only = 1;
+ break;
+ case 10:
+ obtain_sl = 0;
+ break;
+ case 'G':
+ case 'S':
+ port_guid_str = optarg;
+ port_guid = strtoull(optarg, 0, 0);
+ break;
+ case 'D':
+ dr_path = strdup(optarg);
+ break;
+ case 'r':
+ port_config++;
+ break;
+ case 'R': /* nop */
+ break;
+ case 'k':
+ clear_errors = 1;
+ break;
+ case 'K':
+ clear_counts = 1;
+ break;
+ case 'o':
+ cfg->max_smps = strtoul(optarg, NULL, 0);
+ break;
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ struct ibnd_config config = { 0 };
+ int resolved = -1;
+ ib_portid_t portid = { 0 };
+ ib_portid_t self_portid = { 0 };
+ int rc = 0;
+ ibnd_fabric_t *fabric = NULL;
+ ib_gid_t self_gid;
+ int port = 0;
+
+ int mgmt_classes[4] = { IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS,
+ IB_PERFORMANCE_CLASS
+ };
+
+ const struct ibdiag_opt opts[] = {
+ {"suppress", 's', 1, "<err1,err2,...>",
+ "suppress errors listed"},
+ {"suppress-common", 'c', 0, NULL,
+ "suppress some of the common counters"},
+ {"node-name-map", 1, 1, "<file>", "node name map file"},
+ {"port-guid", 'G', 1, "<port_guid>",
+ "report the node containing the port specified by <port_guid>"},
+ {"", 'S', 1, "<port_guid>",
+ "Same as \"-G\" for backward compatibility"},
+ {"Direct", 'D', 1, "<dr_path>",
+ "report the node containing the port specified by <dr_path>"},
+ {"skip-sl", 10, 0, NULL,"don't obtain SL to all destinations"},
+ {"report-port", 'r', 0, NULL,
+ "report port link information"},
+ {"threshold-file", 8, 1, NULL,
+ "specify an alternate threshold file, default: " DEF_THRES_FILE},
+ {"GNDN", 'R', 0, NULL,
+ "(This option is obsolete and does nothing)"},
+ {"data", 2, 0, NULL, "include data counters for ports with errors"},
+ {"switch", 3, 0, NULL, "print data for switches only"},
+ {"ca", 4, 0, NULL, "print data for CA's only"},
+ {"router", 5, 0, NULL, "print data for routers only"},
+ {"details", 6, 0, NULL, "include transmit discard details"},
+ {"counters", 9, 0, NULL, "print data counters only"},
+ {"clear-errors", 'k', 0, NULL,
+ "Clear error counters after read"},
+ {"clear-counts", 'K', 0, NULL,
+ "Clear data counters after read"},
+ {"load-cache", 7, 1, "<file>",
+ "filename of ibnetdiscover cache to load"},
+ {"outstanding_smps", 'o', 1, NULL,
+ "specify the number of outstanding SMP's which should be "
+ "issued during the scan"},
+ {0}
+ };
+ char usage_args[] = "";
+
+ memset(suppressed_fields, 0, sizeof suppressed_fields);
+ ibdiag_process_opts(argc, argv, &config, "cDGKLnRrSs", opts, process_opt,
+ usage_args, NULL);
+
+ argc -= optind;
+ argv += optind;
+
+ if (!node_type_to_print)
+ node_type_to_print = PRINT_ALL;
+
+ ibmad_port = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 4);
+ if (!ibmad_port)
+ IBEXIT("Failed to open port; %s:%d\n", ibd_ca, ibd_ca_port);
+
+ smp_mkey_set(ibmad_port, ibd_mkey);
+
+ if (ibd_timeout) {
+ mad_rpc_set_timeout(ibmad_port, ibd_timeout);
+ config.timeout_ms = ibd_timeout;
+ }
+
+ config.flags = ibd_ibnetdisc_flags;
+ config.mkey = ibd_mkey;
+
+ if (dr_path && load_cache_file) {
+ mad_rpc_close_port(ibmad_port);
+ fprintf(stderr, "Cannot specify cache and direct route path\n");
+ exit(-1);
+ }
+
+ if (resolve_self(ibd_ca, ibd_ca_port, &self_portid, &port, &self_gid.raw) < 0) {
+ mad_rpc_close_port(ibmad_port);
+ IBEXIT("can't resolve self port %s", argv[0]);
+ }
+
+ node_name_map = open_node_name_map(node_name_map_file);
+
+ /* limit the scan the fabric around the target */
+ if (dr_path) {
+ if ((resolved =
+ resolve_portid_str(ibd_ca, ibd_ca_port, &portid, dr_path,
+ IB_DEST_DRPATH, NULL, ibmad_port)) < 0)
+ IBWARN("Failed to resolve %s; attempting full scan",
+ dr_path);
+ } else if (port_guid_str) {
+ if ((resolved =
+ resolve_portid_str(ibd_ca, ibd_ca_port, &portid,
+ port_guid_str, IB_DEST_GUID, ibd_sm_id,
+ ibmad_port)) < 0)
+ IBWARN("Failed to resolve %s; attempting full scan",
+ port_guid_str);
+ if(obtain_sl)
+ lid2sl_table[portid.lid] = portid.sl;
+ }
+
+ mad_rpc_close_port(ibmad_port);
+
+ if (load_cache_file) {
+ if ((fabric = ibnd_load_fabric(load_cache_file, 0)) == NULL) {
+ fprintf(stderr, "loading cached fabric failed\n");
+ rc = -1;
+ goto close_port;
+ }
+ } else {
+ if (resolved >= 0) {
+ if (!config.max_hops)
+ config.max_hops = 1;
+ if (!(fabric = ibnd_discover_fabric(ibd_ca, ibd_ca_port,
+ &portid, &config)))
+ IBWARN("Single node discover failed;"
+ " attempting full scan");
+ }
+
+ if (!fabric && !(fabric = ibnd_discover_fabric(ibd_ca,
+ ibd_ca_port,
+ NULL,
+ &config))) {
+ fprintf(stderr, "discover failed\n");
+ rc = -1;
+ goto close_port;
+ }
+ }
+
+ set_thresholds(threshold_file);
+
+ /* reopen the global ibmad_port */
+ ibmad_port = mad_rpc_open_port(ibd_ca, ibd_ca_port,
+ mgmt_classes, 4);
+ if (!ibmad_port) {
+ ibnd_destroy_fabric(fabric);
+ close_node_name_map(node_name_map);
+ IBEXIT("Failed to reopen port: %s:%d\n",
+ ibd_ca, ibd_ca_port);
+ }
+
+ smp_mkey_set(ibmad_port, ibd_mkey);
+
+ if (ibd_timeout)
+ mad_rpc_set_timeout(ibmad_port, ibd_timeout);
+
+ if (port_guid_str) {
+ ibnd_port_t *port = ibnd_find_port_guid(fabric, port_guid);
+ if (port)
+ print_node(port->node, NULL);
+ else
+ fprintf(stderr, "Failed to find node: %s\n",
+ port_guid_str);
+ } else if (dr_path) {
+ ibnd_port_t *port;
+ uint8_t ni[IB_SMP_DATA_SIZE] = { 0 };
+ if (!smp_query_via(ni, &portid, IB_ATTR_NODE_INFO, 0,
+ ibd_timeout, ibmad_port)) {
+ fprintf(stderr, "Failed to query local Node Info\n");
+ goto destroy_fabric;
+ }
+
+ mad_decode_field(ni, IB_NODE_PORT_GUID_F, &(port_guid));
+
+ port = ibnd_find_port_guid(fabric, port_guid);
+ if (port) {
+ if(obtain_sl)
+ if(path_record_query(self_gid,port->guid))
+ goto destroy_fabric;
+ print_node(port->node, NULL);
+ } else
+ fprintf(stderr, "Failed to find node: %s\n", dr_path);
+ } else {
+ if(obtain_sl)
+ if(path_record_query(self_gid,0))
+ goto destroy_fabric;
+
+ ibnd_iter_nodes(fabric, print_node, NULL);
+ }
+
+ rc = print_summary();
+ if (rc)
+ rc = 1;
+
+destroy_fabric:
+ mad_rpc_close_port(ibmad_port);
+ ibnd_destroy_fabric(fabric);
+
+close_port:
+ close_node_name_map(node_name_map);
+ exit(rc);
+}
diff --git a/contrib/ofed/infiniband-diags/src/ibroute.c b/contrib/ofed/infiniband-diags/src/ibroute.c
new file mode 100644
index 000000000000..8e4544edb6e3
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/src/ibroute.c
@@ -0,0 +1,488 @@
+/*
+ * Copyright (c) 2004-2009 Voltaire Inc. All rights reserved.
+ * Copyright (c) 2009-2011 Mellanox Technologies LTD. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <inttypes.h>
+#include <getopt.h>
+#include <netinet/in.h>
+
+#include <infiniband/umad.h>
+#include <infiniband/mad.h>
+#include <complib/cl_nodenamemap.h>
+
+#include "ibdiag_common.h"
+
+struct ibmad_port *srcport;
+
+static int brief, dump_all, multicast;
+
+static char *node_name_map_file = NULL;
+static nn_map_t *node_name_map = NULL;
+
+/*******************************************/
+
+char *check_switch(ib_portid_t * portid, unsigned int *nports, uint64_t * guid,
+ uint8_t * sw, char *nd)
+{
+ uint8_t ni[IB_SMP_DATA_SIZE] = { 0 };
+ int type;
+
+ DEBUG("checking node type");
+ if (!smp_query_via(ni, portid, IB_ATTR_NODE_INFO, 0, 0, srcport)) {
+ xdump(stderr, "nodeinfo\n", ni, sizeof ni);
+ return "node info failed: valid addr?";
+ }
+
+ if (!smp_query_via(nd, portid, IB_ATTR_NODE_DESC, 0, 0, srcport))
+ return "node desc failed";
+
+ mad_decode_field(ni, IB_NODE_TYPE_F, &type);
+ if (type != IB_NODE_SWITCH)
+ return "not a switch";
+
+ DEBUG("Gathering information about switch");
+ mad_decode_field(ni, IB_NODE_NPORTS_F, nports);
+ mad_decode_field(ni, IB_NODE_GUID_F, guid);
+
+ if (!smp_query_via(sw, portid, IB_ATTR_SWITCH_INFO, 0, 0, srcport))
+ return "switch info failed: is a switch node?";
+
+ return 0;
+}
+
+#define IB_MLIDS_IN_BLOCK (IB_SMP_DATA_SIZE/2)
+
+int dump_mlid(char *str, int strlen, unsigned mlid, unsigned nports,
+ uint16_t mft[16][IB_MLIDS_IN_BLOCK])
+{
+ uint16_t mask;
+ unsigned i, chunk, bit, nonzero = 0;
+
+ if (brief) {
+ int n = 0;
+ unsigned chunks = ALIGN(nports + 1, 16) / 16;
+ for (i = 0; i < chunks; i++) {
+ mask = ntohs(mft[i][mlid % IB_MLIDS_IN_BLOCK]);
+ if (mask)
+ nonzero++;
+ n += snprintf(str + n, strlen - n, "%04hx", mask);
+ if (n >= strlen) {
+ n = strlen;
+ break;
+ }
+ }
+ if (!nonzero && !dump_all) {
+ str[0] = 0;
+ return 0;
+ }
+ return n;
+ }
+ for (i = 0; i <= nports; i++) {
+ chunk = i / 16;
+ bit = i % 16;
+
+ mask = ntohs(mft[chunk][mlid % IB_MLIDS_IN_BLOCK]);
+ if (mask)
+ nonzero++;
+ str[i * 2] = (mask & (1 << bit)) ? 'x' : ' ';
+ str[i * 2 + 1] = ' ';
+ }
+ if (!nonzero && !dump_all) {
+ str[0] = 0;
+ return 0;
+ }
+ str[i * 2] = 0;
+ return i * 2;
+}
+
+uint16_t mft[16][IB_MLIDS_IN_BLOCK] = { { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0 }, { 0}, { 0 }, { 0 } };
+
+char *dump_multicast_tables(ib_portid_t * portid, unsigned startlid,
+ unsigned endlid)
+{
+ char nd[IB_SMP_DATA_SIZE] = { 0 };
+ uint8_t sw[IB_SMP_DATA_SIZE] = { 0 };
+ char str[512];
+ char *s;
+ uint64_t nodeguid;
+ uint32_t mod;
+ unsigned block, i, j, e, nports, cap, chunks, startblock, lastblock,
+ top;
+ char *mapnd = NULL;
+ int n = 0;
+
+ if ((s = check_switch(portid, &nports, &nodeguid, sw, nd)))
+ return s;
+
+ mad_decode_field(sw, IB_SW_MCAST_FDB_CAP_F, &cap);
+ mad_decode_field(sw, IB_SW_MCAST_FDB_TOP_F, &top);
+
+ if (!endlid || endlid > IB_MIN_MCAST_LID + cap - 1)
+ endlid = IB_MIN_MCAST_LID + cap - 1;
+ if (!dump_all && top && top < endlid) {
+ if (top < IB_MIN_MCAST_LID - 1)
+ IBWARN("illegal top mlid %x", top);
+ else
+ endlid = top;
+ }
+
+ if (!startlid)
+ startlid = IB_MIN_MCAST_LID;
+ else if (startlid < IB_MIN_MCAST_LID) {
+ IBWARN("illegal start mlid %x, set to %x", startlid,
+ IB_MIN_MCAST_LID);
+ startlid = IB_MIN_MCAST_LID;
+ }
+
+ if (endlid > IB_MAX_MCAST_LID) {
+ IBWARN("illegal end mlid %x, truncate to %x", endlid,
+ IB_MAX_MCAST_LID);
+ endlid = IB_MAX_MCAST_LID;
+ }
+
+ mapnd = remap_node_name(node_name_map, nodeguid, nd);
+
+ printf("Multicast mlids [0x%x-0x%x] of switch %s guid 0x%016" PRIx64
+ " (%s):\n", startlid, endlid, portid2str(portid), nodeguid,
+ mapnd);
+
+ if (brief)
+ printf(" MLid Port Mask\n");
+ else {
+ if (nports > 9) {
+ for (i = 0, s = str; i <= nports; i++) {
+ *s++ = (i % 10) ? ' ' : '0' + i / 10;
+ *s++ = ' ';
+ }
+ *s = 0;
+ printf(" %s\n", str);
+ }
+ for (i = 0, s = str; i <= nports; i++)
+ s += sprintf(s, "%d ", i % 10);
+ printf(" Ports: %s\n", str);
+ printf(" MLid\n");
+ }
+ if (ibverbose)
+ printf("Switch multicast mlid capability is %d top is 0x%x\n",
+ cap, top);
+
+ chunks = ALIGN(nports + 1, 16) / 16;
+
+ startblock = startlid / IB_MLIDS_IN_BLOCK;
+ lastblock = endlid / IB_MLIDS_IN_BLOCK;
+ for (block = startblock; block <= lastblock; block++) {
+ for (j = 0; j < chunks; j++) {
+ int status;
+ mod = (block - IB_MIN_MCAST_LID / IB_MLIDS_IN_BLOCK)
+ | (j << 28);
+
+ DEBUG("reading block %x chunk %d mod %x", block, j,
+ mod);
+ if (!smp_query_status_via
+ (mft + j, portid, IB_ATTR_MULTICASTFORWTBL, mod, 0,
+ &status, srcport)) {
+ fprintf(stderr, "SubnGet() failed"
+ "; MAD status 0x%x AM 0x%x\n",
+ status, mod);
+ return NULL;
+ }
+ }
+
+ i = block * IB_MLIDS_IN_BLOCK;
+ e = i + IB_MLIDS_IN_BLOCK;
+ if (i < startlid)
+ i = startlid;
+ if (e > endlid + 1)
+ e = endlid + 1;
+
+ for (; i < e; i++) {
+ if (dump_mlid(str, sizeof str, i, nports, mft) == 0)
+ continue;
+ printf("0x%04x %s\n", i, str);
+ n++;
+ }
+ }
+
+ printf("%d %smlids dumped \n", n, dump_all ? "" : "valid ");
+
+ free(mapnd);
+ return 0;
+}
+
+int dump_lid(char *str, int strlen, int lid, int valid)
+{
+ char nd[IB_SMP_DATA_SIZE] = { 0 };
+ uint8_t ni[IB_SMP_DATA_SIZE] = { 0 };
+ uint8_t pi[IB_SMP_DATA_SIZE] = { 0 };
+ ib_portid_t lidport = { 0 };
+ static int last_port_lid, base_port_lid;
+ char ntype[50], sguid[30];
+ static uint64_t portguid;
+ uint64_t nodeguid;
+ int baselid, lmc, type;
+ char *mapnd = NULL;
+ int rc;
+
+ if (brief) {
+ str[0] = 0;
+ return 0;
+ }
+
+ if (lid <= last_port_lid) {
+ if (!valid)
+ return snprintf(str, strlen,
+ ": (path #%d - illegal port)",
+ lid - base_port_lid);
+ else if (!portguid)
+ return snprintf(str, strlen,
+ ": (path #%d out of %d)",
+ lid - base_port_lid + 1,
+ last_port_lid - base_port_lid + 1);
+ else {
+ return snprintf(str, strlen,
+ ": (path #%d out of %d: portguid %s)",
+ lid - base_port_lid + 1,
+ last_port_lid - base_port_lid + 1,
+ mad_dump_val(IB_NODE_PORT_GUID_F, sguid,
+ sizeof sguid, &portguid));
+ }
+ }
+
+ if (!valid)
+ return snprintf(str, strlen, ": (illegal port)");
+
+ portguid = 0;
+ lidport.lid = lid;
+
+ if (!smp_query_via(nd, &lidport, IB_ATTR_NODE_DESC, 0, 100, srcport) ||
+ !smp_query_via(pi, &lidport, IB_ATTR_PORT_INFO, 0, 100, srcport) ||
+ !smp_query_via(ni, &lidport, IB_ATTR_NODE_INFO, 0, 100, srcport))
+ return snprintf(str, strlen, ": (unknown node and type)");
+
+ mad_decode_field(ni, IB_NODE_GUID_F, &nodeguid);
+ mad_decode_field(ni, IB_NODE_PORT_GUID_F, &portguid);
+ mad_decode_field(ni, IB_NODE_TYPE_F, &type);
+
+ mad_decode_field(pi, IB_PORT_LID_F, &baselid);
+ mad_decode_field(pi, IB_PORT_LMC_F, &lmc);
+
+ if (lmc > 0) {
+ base_port_lid = baselid;
+ last_port_lid = baselid + (1 << lmc) - 1;
+ }
+
+ mapnd = remap_node_name(node_name_map, nodeguid, nd);
+
+ rc = snprintf(str, strlen, ": (%s portguid %s: '%s')",
+ mad_dump_val(IB_NODE_TYPE_F, ntype, sizeof ntype,
+ &type), mad_dump_val(IB_NODE_PORT_GUID_F,
+ sguid, sizeof sguid,
+ &portguid),
+ mapnd);
+
+ free(mapnd);
+ return rc;
+}
+
+char *dump_unicast_tables(ib_portid_t * portid, int startlid, int endlid)
+{
+ char lft[IB_SMP_DATA_SIZE] = { 0 };
+ char nd[IB_SMP_DATA_SIZE] = { 0 };
+ uint8_t sw[IB_SMP_DATA_SIZE] = { 0 };
+ char str[200], *s;
+ uint64_t nodeguid;
+ int block, i, e, top;
+ unsigned nports;
+ int n = 0, startblock, endblock;
+ char *mapnd = NULL;
+
+ if ((s = check_switch(portid, &nports, &nodeguid, sw, nd)))
+ return s;
+
+ mad_decode_field(sw, IB_SW_LINEAR_FDB_TOP_F, &top);
+
+ if (!endlid || endlid > top)
+ endlid = top;
+
+ if (endlid > IB_MAX_UCAST_LID) {
+ IBWARN("illegal lft top %d, truncate to %d", endlid,
+ IB_MAX_UCAST_LID);
+ endlid = IB_MAX_UCAST_LID;
+ }
+
+ mapnd = remap_node_name(node_name_map, nodeguid, nd);
+
+ printf("Unicast lids [0x%x-0x%x] of switch %s guid 0x%016" PRIx64
+ " (%s):\n", startlid, endlid, portid2str(portid), nodeguid,
+ mapnd);
+
+ DEBUG("Switch top is 0x%x\n", top);
+
+ printf(" Lid Out Destination\n");
+ printf(" Port Info \n");
+ startblock = startlid / IB_SMP_DATA_SIZE;
+ endblock = ALIGN(endlid, IB_SMP_DATA_SIZE) / IB_SMP_DATA_SIZE;
+ for (block = startblock; block < endblock; block++) {
+ int status;
+ DEBUG("reading block %d", block);
+ if (!smp_query_status_via(lft, portid, IB_ATTR_LINEARFORWTBL, block,
+ 0, &status, srcport)) {
+ fprintf(stderr, "SubnGet() failed"
+ "; MAD status 0x%x AM 0x%x\n",
+ status, block);
+ return NULL;
+ }
+ i = block * IB_SMP_DATA_SIZE;
+ e = i + IB_SMP_DATA_SIZE;
+ if (i < startlid)
+ i = startlid;
+ if (e > endlid + 1)
+ e = endlid + 1;
+
+ for (; i < e; i++) {
+ unsigned outport = lft[i % IB_SMP_DATA_SIZE];
+ unsigned valid = (outport <= nports);
+
+ if (!valid && !dump_all)
+ continue;
+ dump_lid(str, sizeof str, i, valid);
+ printf("0x%04x %03u %s\n", i, outport & 0xff, str);
+ n++;
+ }
+ }
+
+ printf("%d %slids dumped \n", n, dump_all ? "" : "valid ");
+ free(mapnd);
+ return 0;
+}
+
+static int process_opt(void *context, int ch, char *optarg)
+{
+ switch (ch) {
+ case 'a':
+ dump_all++;
+ break;
+ case 'M':
+ multicast++;
+ break;
+ case 'n':
+ brief++;
+ break;
+ case 1:
+ node_name_map_file = strdup(optarg);
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ int mgmt_classes[3] =
+ { IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS };
+ ib_portid_t portid = { 0 };
+ unsigned startlid = 0, endlid = 0;
+ char *err;
+
+ const struct ibdiag_opt opts[] = {
+ {"all", 'a', 0, NULL, "show all lids, even invalid entries"},
+ {"no_dests", 'n', 0, NULL,
+ "do not try to resolve destinations"},
+ {"Multicast", 'M', 0, NULL, "show multicast forwarding tables"},
+ {"node-name-map", 1, 1, "<file>", "node name map file"},
+ {0}
+ };
+ char usage_args[] = "[<dest dr_path|lid|guid> [<startlid> [<endlid>]]]";
+ const char *usage_examples[] = {
+ " -- Unicast examples:",
+ "4\t# dump all lids with valid out ports of switch with lid 4",
+ "-a 4\t# same, but dump all lids, even with invalid out ports",
+ "-n 4\t# simple dump format - no destination resolving",
+ "4 10\t# dump lids starting from 10",
+ "4 0x10 0x20\t# dump lid range",
+ "-G 0x08f1040023\t# resolve switch by GUID",
+ "-D 0,1\t# resolve switch by direct path",
+ " -- Multicast examples:",
+ "-M 4\t# dump all non empty mlids of switch with lid 4",
+ "-M 4 0xc010 0xc020\t# same, but with range",
+ "-M -n 4\t# simple dump format",
+ NULL,
+ };
+
+ ibdiag_process_opts(argc, argv, NULL, "K", opts, process_opt,
+ usage_args, usage_examples);
+
+ argc -= optind;
+ argv += optind;
+
+ if (!argc)
+ ibdiag_show_usage();
+
+ if (argc > 1)
+ startlid = strtoul(argv[1], 0, 0);
+ if (argc > 2)
+ endlid = strtoul(argv[2], 0, 0);
+
+ node_name_map = open_node_name_map(node_name_map_file);
+
+ srcport = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 3);
+ if (!srcport)
+ IBEXIT("Failed to open '%s' port '%d'", ibd_ca, ibd_ca_port);
+
+ smp_mkey_set(srcport, ibd_mkey);
+
+ if (resolve_portid_str(ibd_ca, ibd_ca_port, &portid, argv[0],
+ ibd_dest_type, ibd_sm_id, srcport) < 0)
+ IBEXIT("can't resolve destination port %s", argv[0]);
+
+ if (multicast)
+ err = dump_multicast_tables(&portid, startlid, endlid);
+ else
+ err = dump_unicast_tables(&portid, startlid, endlid);
+
+ if (err)
+ IBEXIT("dump tables: %s", err);
+
+ mad_rpc_close_port(srcport);
+ close_node_name_map(node_name_map);
+ exit(0);
+}
diff --git a/contrib/ofed/infiniband-diags/src/ibsendtrap.c b/contrib/ofed/infiniband-diags/src/ibsendtrap.c
new file mode 100644
index 000000000000..7044deb783d8
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/src/ibsendtrap.c
@@ -0,0 +1,278 @@
+/*
+ * Copyright (c) 2008 Lawrence Livermore National Security
+ * Copyright (c) 2008-2009 Voltaire Inc. All rights reserved.
+ * Copyright (c) 2009 HNR Consulting. All rights reserved.
+ * Copyright (c) 2011 Mellanox Technologies LTD. All rights reserved.
+ *
+ * Produced at Lawrence Livermore National Laboratory.
+ * Written by Ira Weiny <weiny2@llnl.gov>.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+
+#define _GNU_SOURCE
+#include <getopt.h>
+
+#include <infiniband/mad.h>
+#include <iba/ib_types.h>
+
+#include "ibdiag_common.h"
+
+struct ibmad_port *srcport;
+/* for local link integrity */
+int error_port = 1;
+
+static uint16_t get_node_type(ib_portid_t * port)
+{
+ uint16_t node_type = IB_NODE_TYPE_CA;
+ uint8_t data[IB_SMP_DATA_SIZE] = { 0 };
+
+ if (smp_query_via(data, port, IB_ATTR_NODE_INFO, 0, 0, srcport))
+ node_type = (uint16_t) mad_get_field(data, 0, IB_NODE_TYPE_F);
+ return node_type;
+}
+
+static uint32_t get_cap_mask(ib_portid_t * port)
+{
+ uint8_t data[IB_SMP_DATA_SIZE] = { 0 };
+ uint32_t cap_mask = 0;
+
+ if (smp_query_via(data, port, IB_ATTR_PORT_INFO, 0, 0, srcport))
+ cap_mask = (uint32_t) mad_get_field(data, 0, IB_PORT_CAPMASK_F);
+ return cap_mask;
+}
+
+static void build_trap145(ib_mad_notice_attr_t * n, ib_portid_t * port)
+{
+ n->generic_type = 0x80 | IB_NOTICE_TYPE_INFO;
+ n->g_or_v.generic.prod_type_lsb = cl_hton16(get_node_type(port));
+ n->g_or_v.generic.trap_num = cl_hton16(145);
+ n->issuer_lid = cl_hton16((uint16_t) port->lid);
+ n->data_details.ntc_145.new_sys_guid = cl_hton64(0x1234567812345678);
+}
+
+static void build_trap144_local(ib_mad_notice_attr_t * n, ib_portid_t * port)
+{
+ n->generic_type = 0x80 | IB_NOTICE_TYPE_INFO;
+ n->g_or_v.generic.prod_type_lsb = cl_hton16(get_node_type(port));
+ n->g_or_v.generic.trap_num = cl_hton16(144);
+ n->issuer_lid = cl_hton16((uint16_t) port->lid);
+ n->data_details.ntc_144.lid = n->issuer_lid;
+ n->data_details.ntc_144.new_cap_mask = cl_hton32(get_cap_mask(port));
+ n->data_details.ntc_144.local_changes =
+ TRAP_144_MASK_OTHER_LOCAL_CHANGES;
+}
+
+static void build_trap144_nodedesc(ib_mad_notice_attr_t * n, ib_portid_t * port)
+{
+ build_trap144_local(n, port);
+ n->data_details.ntc_144.change_flgs =
+ TRAP_144_MASK_NODE_DESCRIPTION_CHANGE;
+}
+
+static void build_trap144_linkspeed(ib_mad_notice_attr_t * n,
+ ib_portid_t * port)
+{
+ build_trap144_local(n, port);
+ n->data_details.ntc_144.change_flgs =
+ TRAP_144_MASK_LINK_SPEED_ENABLE_CHANGE;
+}
+
+static void build_trap129(ib_mad_notice_attr_t * n, ib_portid_t * port)
+{
+ n->generic_type = 0x80 | IB_NOTICE_TYPE_URGENT;
+ n->g_or_v.generic.prod_type_lsb = cl_hton16(get_node_type(port));
+ n->g_or_v.generic.trap_num = cl_hton16(129);
+ n->issuer_lid = cl_hton16((uint16_t) port->lid);
+ n->data_details.ntc_129_131.lid = n->issuer_lid;
+ n->data_details.ntc_129_131.pad = 0;
+ n->data_details.ntc_129_131.port_num = (uint8_t) error_port;
+}
+
+static void build_trap256_local(ib_mad_notice_attr_t * n, ib_portid_t * port)
+{
+ n->generic_type = 0x80 | IB_NOTICE_TYPE_SECURITY;
+ n->g_or_v.generic.prod_type_lsb = cl_hton16(get_node_type(port));
+ n->g_or_v.generic.trap_num = cl_hton16(256);
+ n->issuer_lid = cl_hton16((uint16_t) port->lid);
+ n->data_details.ntc_256.lid = n->issuer_lid;
+ n->data_details.ntc_256.dr_slid = 0xffff;
+ n->data_details.ntc_256.method = 1;
+ n->data_details.ntc_256.attr_id = cl_ntoh16(0x15);
+ n->data_details.ntc_256.attr_mod = cl_ntoh32(0x12);
+ n->data_details.ntc_256.mkey = cl_ntoh64(0x1234567812345678);
+}
+
+static void build_trap256_lid(ib_mad_notice_attr_t * n, ib_portid_t * port)
+{
+ build_trap256_local(n, port);
+ n->data_details.ntc_256.dr_trunc_hop = 0;
+}
+
+static void build_trap256_dr(ib_mad_notice_attr_t * n, ib_portid_t * port)
+{
+ build_trap256_local(n, port);
+ n->data_details.ntc_256.dr_trunc_hop = 0x80 | 0x4;
+ n->data_details.ntc_256.dr_rtn_path[0] = 5;
+ n->data_details.ntc_256.dr_rtn_path[1] = 6;
+ n->data_details.ntc_256.dr_rtn_path[2] = 7;
+ n->data_details.ntc_256.dr_rtn_path[3] = 8;
+}
+
+static void build_trap257_258(ib_mad_notice_attr_t * n, ib_portid_t * port,
+ uint16_t trap_num)
+{
+ n->generic_type = 0x80 | IB_NOTICE_TYPE_SECURITY;
+ n->g_or_v.generic.prod_type_lsb = cl_hton16(get_node_type(port));
+ n->g_or_v.generic.trap_num = cl_hton16(trap_num);
+ n->issuer_lid = cl_hton16((uint16_t) port->lid);
+ n->data_details.ntc_257_258.lid1 = cl_hton16(1);
+ n->data_details.ntc_257_258.lid2 = cl_hton16(2);
+ n->data_details.ntc_257_258.key = cl_hton32(0x12345678);
+ n->data_details.ntc_257_258.qp1 = cl_hton32(0x010101);
+ n->data_details.ntc_257_258.qp2 = cl_hton32(0x020202);
+ n->data_details.ntc_257_258.gid1.unicast.prefix = cl_ntoh64(0xf8c0000000000001);
+ n->data_details.ntc_257_258.gid1.unicast.interface_id = cl_ntoh64(0x1111222233334444);
+ n->data_details.ntc_257_258.gid2.unicast.prefix = cl_ntoh64(0xf8c0000000000001);
+ n->data_details.ntc_257_258.gid2.unicast.interface_id = cl_ntoh64(0x5678567812341234);
+}
+
+static void build_trap257(ib_mad_notice_attr_t * n, ib_portid_t * port)
+{
+ build_trap257_258(n, port, 257);
+}
+
+static void build_trap258(ib_mad_notice_attr_t * n, ib_portid_t * port)
+{
+ build_trap257_258(n, port, 258);
+}
+
+static int send_trap(void (*build) (ib_mad_notice_attr_t *, ib_portid_t *))
+{
+ ib_portid_t sm_port;
+ ib_portid_t selfportid;
+ int selfport;
+ ib_rpc_t trap_rpc;
+ ib_mad_notice_attr_t notice;
+
+ if (resolve_self(ibd_ca, ibd_ca_port, &selfportid, &selfport, NULL))
+ IBEXIT("can't resolve self");
+
+ if (resolve_sm_portid(ibd_ca, ibd_ca_port, &sm_port))
+ IBEXIT("can't resolve SM destination port");
+
+ memset(&trap_rpc, 0, sizeof(trap_rpc));
+ trap_rpc.mgtclass = IB_SMI_CLASS;
+ trap_rpc.method = IB_MAD_METHOD_TRAP;
+ trap_rpc.trid = mad_trid();
+ trap_rpc.attr.id = NOTICE;
+ trap_rpc.datasz = IB_SMP_DATA_SIZE;
+ trap_rpc.dataoffs = IB_SMP_DATA_OFFS;
+
+ memset(&notice, 0, sizeof(notice));
+ build(&notice, &selfportid);
+
+ return mad_send_via(&trap_rpc, &sm_port, NULL, &notice, srcport);
+}
+
+typedef struct _trap_def {
+ char *trap_name;
+ void (*build_func) (ib_mad_notice_attr_t *, ib_portid_t *);
+} trap_def_t;
+
+static const trap_def_t traps[] = {
+ {"node_desc_change", build_trap144_nodedesc},
+ {"link_speed_enabled_change", build_trap144_linkspeed},
+ {"local_link_integrity", build_trap129},
+ {"sys_image_guid_change", build_trap145},
+ {"mkey_lid", build_trap256_lid},
+ {"mkey_dr", build_trap256_dr},
+ {"pkey", build_trap257},
+ {"qkey", build_trap258},
+ {NULL, NULL}
+};
+
+int process_send_trap(char *trap_name)
+{
+ int i;
+
+ for (i = 0; traps[i].trap_name; i++)
+ if (strcmp(traps[i].trap_name, trap_name) == 0)
+ return send_trap(traps[i].build_func);
+ ibdiag_show_usage();
+ return 1;
+}
+
+int main(int argc, char **argv)
+{
+ char usage_args[1024];
+ int mgmt_classes[2] = { IB_SMI_CLASS, IB_SMI_DIRECT_CLASS };
+ char *trap_name = NULL;
+ int i, n, rc;
+
+ n = sprintf(usage_args, "[<trap_name>] [<error_port>]\n"
+ "\nArgument <trap_name> can be one of the following:\n");
+ for (i = 0; traps[i].trap_name; i++) {
+ n += snprintf(usage_args + n, sizeof(usage_args) - n,
+ " %s\n", traps[i].trap_name);
+ if (n >= sizeof(usage_args))
+ exit(-1);
+ }
+ snprintf(usage_args + n, sizeof(usage_args) - n,
+ "\n default behavior is to send \"%s\"", traps[0].trap_name);
+
+ ibdiag_process_opts(argc, argv, NULL, "DGKL", NULL, NULL,
+ usage_args, NULL);
+
+ argc -= optind;
+ argv += optind;
+
+ trap_name = argv[0] ? argv[0] : traps[0].trap_name;
+
+ if (argc > 1)
+ error_port = atoi(argv[1]);
+
+ madrpc_show_errors(1);
+
+ srcport = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 2);
+ if (!srcport)
+ IBEXIT("Failed to open '%s' port '%d'", ibd_ca, ibd_ca_port);
+
+ smp_mkey_set(srcport, ibd_mkey);
+
+ rc = process_send_trap(trap_name);
+ mad_rpc_close_port(srcport);
+ return rc;
+}
diff --git a/contrib/ofed/infiniband-diags/src/ibstat.c b/contrib/ofed/infiniband-diags/src/ibstat.c
new file mode 100644
index 000000000000..6e08fad409ca
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/src/ibstat.c
@@ -0,0 +1,335 @@
+/*
+ * Copyright (c) 2004-2009 Voltaire Inc. All rights reserved.
+ * Copyright (c) 2011 Mellanox Technologies LTD. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#define _GNU_SOURCE
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <inttypes.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <netinet/in.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <infiniband/umad.h>
+
+#include <ibdiag_common.h>
+
+static char *node_type_str[] = {
+ "???",
+ "CA",
+ "Switch",
+ "Router",
+ "iWARP RNIC"
+};
+
+static void ca_dump(umad_ca_t * ca)
+{
+ if (!ca->node_type)
+ return;
+ printf("%s '%s'\n",
+ ((unsigned)ca->node_type <=
+ IB_NODE_MAX ? node_type_str[ca->node_type] : "???"),
+ ca->ca_name);
+ printf("\t%s type: %s\n",
+ ((unsigned)ca->node_type <=
+ IB_NODE_MAX ? node_type_str[ca->node_type] : "???"),
+ ca->ca_type);
+ printf("\tNumber of ports: %d\n", ca->numports);
+ printf("\tFirmware version: %s\n", ca->fw_ver);
+ printf("\tHardware version: %s\n", ca->hw_ver);
+ printf("\tNode GUID: 0x%016" PRIx64 "\n", ntohll(ca->node_guid));
+ printf("\tSystem image GUID: 0x%016" PRIx64 "\n",
+ ntohll(ca->system_guid));
+}
+
+static char *port_state_str[] = {
+ "???",
+ "Down",
+ "Initializing",
+ "Armed",
+ "Active"
+};
+
+static char *port_phy_state_str[] = {
+ "No state change",
+ "Sleep",
+ "Polling",
+ "Disabled",
+ "PortConfigurationTraining",
+ "LinkUp",
+ "LinkErrorRecovery",
+ "PhyTest"
+};
+
+static int ret_code(void)
+{
+ int e = errno;
+
+ if (e > 0)
+ return -e;
+ return e;
+}
+
+int sys_read_string(const char *dir_name, const char *file_name, char *str, int max_len)
+{
+ char path[256], *s;
+ size_t len;
+
+ snprintf(path, sizeof(path), "%s/%s", dir_name, file_name);
+
+ for (s = &path[0]; *s != '\0'; s++)
+ if (*s == '/')
+ *s = '.';
+
+ len = max_len;
+ if (sysctlbyname(&path[1], str, &len, NULL, 0) == -1)
+ return ret_code();
+
+ str[(len < max_len) ? len : max_len - 1] = 0;
+
+ if ((s = strrchr(str, '\n')))
+ *s = 0;
+
+ return 0;
+}
+
+static int is_fdr10(umad_port_t *port)
+{
+ char port_dir[256];
+ char rate[32];
+ int len, fdr10 = 0;
+ char *p;
+
+ len = snprintf(port_dir, sizeof(port_dir), "%s/%s/%s/%d",
+ SYS_INFINIBAND, port->ca_name, SYS_CA_PORTS_DIR,
+ port->portnum);
+ if (len < 0 || len > sizeof(port_dir))
+ goto done;
+
+ if (sys_read_string(port_dir, SYS_PORT_RATE, rate, sizeof(rate)) == 0) {
+ if ((p = strchr(rate, ')'))) {
+ if (!strncasecmp(p - 5, "fdr10", 5))
+ fdr10 = 1;
+ }
+ }
+
+done:
+ return fdr10;
+}
+
+static int port_dump(umad_port_t * port, int alone)
+{
+ char *pre = "";
+ char *hdrpre = "";
+
+ if (!port)
+ return -1;
+
+ if (!alone) {
+ pre = " ";
+ hdrpre = " ";
+ }
+
+ printf("%sPort %d:\n", hdrpre, port->portnum);
+ printf("%sState: %s\n", pre,
+ (unsigned)port->state <=
+ 4 ? port_state_str[port->state] : "???");
+ printf("%sPhysical state: %s\n", pre,
+ (unsigned)port->phys_state <=
+ 7 ? port_phy_state_str[port->phys_state] : "???");
+ if (is_fdr10(port))
+ printf("%sRate: %d (FDR10)\n", pre, port->rate);
+ else
+ if (port->rate != 2)
+ printf("%sRate: %d\n", pre, port->rate);
+ else
+ printf("%sRate: 2.5\n", pre);
+ printf("%sBase lid: %d\n", pre, port->base_lid);
+ printf("%sLMC: %d\n", pre, port->lmc);
+ printf("%sSM lid: %d\n", pre, port->sm_lid);
+ printf("%sCapability mask: 0x%08x\n", pre, ntohl(port->capmask));
+ printf("%sPort GUID: 0x%016" PRIx64 "\n", pre, ntohll(port->port_guid));
+#ifdef HAVE_UMAD_PORT_LINK_LAYER
+ printf("%sLink layer: %s\n", pre, port->link_layer);
+#endif
+ return 0;
+}
+
+static int ca_stat(char *ca_name, int portnum, int no_ports)
+{
+ umad_ca_t ca;
+ int r;
+
+ if ((r = umad_get_ca(ca_name, &ca)) < 0)
+ return r;
+
+ if (!ca.node_type)
+ return 0;
+
+ if (!no_ports && portnum >= 0) {
+ if (portnum > ca.numports || !ca.ports[portnum]) {
+ IBWARN("%s: '%s' has no port number %d - max (%d)",
+ ((unsigned)ca.node_type <=
+ IB_NODE_MAX ? node_type_str[ca.node_type] :
+ "???"), ca_name, portnum, ca.numports);
+ return -1;
+ }
+ printf("%s: '%s'\n",
+ ((unsigned)ca.node_type <=
+ IB_NODE_MAX ? node_type_str[ca.node_type] : "???"),
+ ca.ca_name);
+ port_dump(ca.ports[portnum], 1);
+ return 0;
+ }
+
+ /* print ca header */
+ ca_dump(&ca);
+
+ if (no_ports)
+ return 0;
+
+ for (portnum = 0; portnum <= ca.numports; portnum++)
+ port_dump(ca.ports[portnum], 0);
+
+ return 0;
+}
+
+static int ports_list(char names[][UMAD_CA_NAME_LEN], int n)
+{
+ uint64_t guids[64];
+ int found, ports, i;
+
+ for (i = 0, found = 0; i < n && found < 64; i++) {
+ if ((ports =
+ umad_get_ca_portguids(names[i], guids + found,
+ 64 - found)) < 0)
+ return -1;
+ found += ports;
+ }
+
+ for (i = 0; i < found; i++)
+ if (guids[i])
+ printf("0x%016" PRIx64 "\n", ntohll(guids[i]));
+ return found;
+}
+
+static int list_only, short_format, list_ports;
+
+static int process_opt(void *context, int ch, char *optarg)
+{
+ switch (ch) {
+ case 'l':
+ list_only++;
+ break;
+ case 's':
+ short_format++;
+ break;
+ case 'p':
+ list_ports++;
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ char names[UMAD_MAX_DEVICES][UMAD_CA_NAME_LEN];
+ int dev_port = -1;
+ int n, i;
+
+ const struct ibdiag_opt opts[] = {
+ {"list_of_cas", 'l', 0, NULL, "list all IB devices"},
+ {"short", 's', 0, NULL, "short output"},
+ {"port_list", 'p', 0, NULL, "show port list"},
+ {0}
+ };
+ char usage_args[] = "<ca_name> [portnum]";
+ const char *usage_examples[] = {
+ "-l # list all IB devices",
+ "mthca0 2 # stat port 2 of 'mthca0'",
+ NULL
+ };
+
+ ibdiag_process_opts(argc, argv, NULL, "CDeGKLPsty", opts, process_opt,
+ usage_args, usage_examples);
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc > 1)
+ dev_port = strtol(argv[1], 0, 0);
+
+ if (umad_init() < 0)
+ IBPANIC("can't init UMAD library");
+
+ if ((n = umad_get_cas_names(names, UMAD_MAX_DEVICES)) < 0)
+ IBPANIC("can't list IB device names");
+
+ if (argc) {
+ for (i = 0; i < n; i++)
+ if (!strncmp(names[i], argv[0], sizeof names[i]))
+ break;
+ if (i >= n)
+ IBPANIC("'%s' IB device can't be found", argv[0]);
+
+ strncpy(names[0], argv[0], sizeof(names[0])-1);
+ names[0][sizeof(names[0])-1] = '\0';
+ n = 1;
+ }
+
+ if (list_ports) {
+ if (ports_list(names, n) < 0)
+ IBPANIC("can't list ports");
+ return 0;
+ }
+
+ for (i = 0; i < n; i++) {
+ if (list_only)
+ printf("%s\n", names[i]);
+ else if (ca_stat(names[i], dev_port, short_format) < 0)
+ IBPANIC("stat of IB device '%s' failed", names[i]);
+ }
+
+ return 0;
+}
diff --git a/contrib/ofed/infiniband-diags/src/ibsysstat.c b/contrib/ofed/infiniband-diags/src/ibsysstat.c
new file mode 100644
index 000000000000..104306dde276
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/src/ibsysstat.c
@@ -0,0 +1,367 @@
+/*
+ * Copyright (c) 2004-2009 Voltaire Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <getopt.h>
+
+#include <infiniband/umad.h>
+#include <infiniband/mad.h>
+
+#include <sys/sysctl.h>
+
+#include "ibdiag_common.h"
+
+#define MAX_CPUS 8
+
+struct ibmad_port *srcport;
+
+static ibmad_gid_t dgid;
+static int with_grh;
+
+enum ib_sysstat_attr_t {
+ IB_PING_ATTR = 0x10,
+ IB_HOSTINFO_ATTR = 0x11,
+ IB_CPUINFO_ATTR = 0x12,
+};
+
+typedef struct cpu_info {
+ char *model;
+ char *mhz;
+} cpu_info;
+
+static cpu_info cpus[MAX_CPUS];
+static int host_ncpu;
+static int server = 0, oui = IB_OPENIB_OUI;
+
+static int server_respond(void *umad, int size)
+{
+ ib_rpc_t rpc = { 0 };
+ ib_rmpp_hdr_t rmpp = { 0 };
+ ib_portid_t rport;
+ uint8_t *mad = umad_get_mad(umad);
+ ib_mad_addr_t *mad_addr;
+
+ if (!(mad_addr = umad_get_mad_addr(umad)))
+ return -1;
+
+ memset(&rport, 0, sizeof(rport));
+
+ rport.lid = ntohs(mad_addr->lid);
+ rport.qp = ntohl(mad_addr->qpn);
+ rport.qkey = ntohl(mad_addr->qkey);
+ rport.sl = mad_addr->sl;
+ if (!rport.qkey && rport.qp == 1)
+ rport.qkey = IB_DEFAULT_QP1_QKEY;
+ rport.grh_present = mad_addr->grh_present;
+ if (rport.grh_present)
+ memcpy(rport.gid, mad_addr->gid, 16);
+
+ rpc.mgtclass = mad_get_field(mad, 0, IB_MAD_MGMTCLASS_F);
+ rpc.method = IB_MAD_METHOD_GET | IB_MAD_RESPONSE;
+ rpc.attr.id = mad_get_field(mad, 0, IB_MAD_ATTRID_F);
+ rpc.attr.mod = mad_get_field(mad, 0, IB_MAD_ATTRMOD_F);
+ rpc.oui = mad_get_field(mad, 0, IB_VEND2_OUI_F);
+ rpc.trid = mad_get_field64(mad, 0, IB_MAD_TRID_F);
+
+ if (size > IB_MAD_SIZE)
+ rmpp.flags = IB_RMPP_FLAG_ACTIVE;
+
+ DEBUG("responding %d bytes to %s, attr 0x%x mod 0x%x qkey %x",
+ size, portid2str(&rport), rpc.attr.id, rpc.attr.mod, rport.qkey);
+
+ if (mad_build_pkt(umad, &rpc, &rport, &rmpp, 0) < 0)
+ return -1;
+
+ if (ibdebug > 1)
+ xdump(stderr, "mad respond pkt\n", mad, IB_MAD_SIZE);
+
+ if (umad_send(mad_rpc_portid(srcport),
+ mad_rpc_class_agent(srcport, rpc.mgtclass), umad, size,
+ rpc.timeout, 0) < 0) {
+ DEBUG("send failed; %m");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int mk_reply(int attr, void *data, int sz)
+{
+ char *s = data;
+ int n, i, ret = 0;
+
+ switch (attr) {
+ case IB_PING_ATTR:
+ break; /* nothing to do here, just reply */
+ case IB_HOSTINFO_ATTR:
+ if (gethostname(s, sz) < 0)
+ snprintf(s, sz, "?hostname?");
+ s[sz - 1] = 0;
+ if ((n = strlen(s)) >= sz - 1) {
+ ret = sz;
+ break;
+ }
+ s[n] = '.';
+ s += n + 1;
+ sz -= n + 1;
+ ret += n + 1;
+ if (getdomainname(s, sz) < 0)
+ snprintf(s, sz, "?domainname?");
+ if ((n = strlen(s)) == 0)
+ s[-1] = 0; /* no domain */
+ else
+ ret += n;
+ break;
+ case IB_CPUINFO_ATTR:
+ s[0] = '\0';
+ for (i = 0; i < host_ncpu && sz > 0; i++) {
+ n = snprintf(s, sz, "cpu %d: model %s MHZ %s\n",
+ i, cpus[i].model, cpus[i].mhz);
+ if (n >= sz) {
+ IBWARN("cpuinfo truncated");
+ ret = sz;
+ break;
+ }
+ sz -= n;
+ s += n;
+ ret += n;
+ }
+ ret++;
+ break;
+ default:
+ DEBUG("unknown attr %d", attr);
+ }
+ return ret;
+}
+
+static uint8_t buf[2048];
+
+static char *ibsystat_serv(void)
+{
+ void *umad;
+ void *mad;
+ int attr, mod, size;
+
+ DEBUG("starting to serve...");
+
+ while ((umad = mad_receive_via(buf, -1, srcport))) {
+ if (umad_status(buf)) {
+ DEBUG("drop mad with status %x: %s", umad_status(buf),
+ strerror(umad_status(buf)));
+ continue;
+ }
+
+ mad = umad_get_mad(umad);
+
+ attr = mad_get_field(mad, 0, IB_MAD_ATTRID_F);
+ mod = mad_get_field(mad, 0, IB_MAD_ATTRMOD_F);
+
+ DEBUG("got packet: attr 0x%x mod 0x%x", attr, mod);
+
+ size =
+ mk_reply(attr, (uint8_t *) mad + IB_VENDOR_RANGE2_DATA_OFFS,
+ sizeof(buf) - umad_size() -
+ IB_VENDOR_RANGE2_DATA_OFFS);
+
+ if (server_respond(umad, IB_VENDOR_RANGE2_DATA_OFFS + size) < 0)
+ DEBUG("respond failed");
+ }
+
+ DEBUG("server out");
+ return 0;
+}
+
+static int match_attr(char *str)
+{
+ if (!strcmp(str, "ping"))
+ return IB_PING_ATTR;
+ if (!strcmp(str, "host"))
+ return IB_HOSTINFO_ATTR;
+ if (!strcmp(str, "cpu"))
+ return IB_CPUINFO_ATTR;
+ return -1;
+}
+
+static char *ibsystat(ib_portid_t * portid, int attr)
+{
+ ib_rpc_t rpc = { 0 };
+ int fd, agent, timeout, len;
+ void *data = (uint8_t *) umad_get_mad(buf) + IB_VENDOR_RANGE2_DATA_OFFS;
+
+ DEBUG("Sysstat ping..");
+
+ rpc.mgtclass = IB_VENDOR_OPENIB_SYSSTAT_CLASS;
+ rpc.method = IB_MAD_METHOD_GET;
+ rpc.attr.id = attr;
+ rpc.attr.mod = 0;
+ rpc.oui = oui;
+ rpc.timeout = 0;
+ rpc.datasz = IB_VENDOR_RANGE2_DATA_SIZE;
+ rpc.dataoffs = IB_VENDOR_RANGE2_DATA_OFFS;
+
+ portid->qp = 1;
+ if (!portid->qkey)
+ portid->qkey = IB_DEFAULT_QP1_QKEY;
+
+ if ((len = mad_build_pkt(buf, &rpc, portid, NULL, NULL)) < 0)
+ IBPANIC("cannot build packet.");
+
+ fd = mad_rpc_portid(srcport);
+ agent = mad_rpc_class_agent(srcport, rpc.mgtclass);
+ timeout = ibd_timeout ? ibd_timeout : MAD_DEF_TIMEOUT_MS;
+
+ if (umad_send(fd, agent, buf, len, timeout, 0) < 0)
+ IBPANIC("umad_send failed.");
+
+ len = sizeof(buf) - umad_size();
+ if (umad_recv(fd, buf, &len, timeout) < 0)
+ IBPANIC("umad_recv failed.");
+
+ if (umad_status(buf))
+ return strerror(umad_status(buf));
+
+ DEBUG("Got sysstat pong..");
+ if (attr != IB_PING_ATTR)
+ puts(data);
+ else
+ printf("sysstat ping succeeded\n");
+ return 0;
+}
+
+int build_cpuinfo(void)
+{
+ int ret;
+ size_t size = sizeof(ret);
+
+ if (sysctlbyname("hw.ncpu", &ret, &size, NULL, 0) != 0 || ret < 1)
+ ret = 1;
+ return ret;
+
+ DEBUG("ncpu %d", ret);
+}
+
+static int process_opt(void *context, int ch, char *optarg)
+{
+ switch (ch) {
+ case 'o':
+ oui = strtoul(optarg, 0, 0);
+ break;
+ case 'S':
+ server++;
+ break;
+ case 25:
+ if (!inet_pton(AF_INET6, optarg, &dgid)) {
+ fprintf(stderr, "dgid format is wrong!\n");
+ ibdiag_show_usage();
+ return 1;
+ }
+ with_grh = 1;
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ int mgmt_classes[3] =
+ { IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS };
+ int sysstat_class = IB_VENDOR_OPENIB_SYSSTAT_CLASS;
+ ib_portid_t portid = { 0 };
+ int attr = IB_PING_ATTR;
+ char *err;
+
+ const struct ibdiag_opt opts[] = {
+ {"oui", 'o', 1, NULL, "use specified OUI number"},
+ {"Server", 'S', 0, NULL, "start in server mode"},
+ {"dgid", 25, 1, NULL, "remote gid (IPv6 format)"},
+ {0}
+ };
+ char usage_args[] = "<dest lid|guid> [<op>]";
+
+ ibdiag_process_opts(argc, argv, NULL, "DKy", opts, process_opt,
+ usage_args, NULL);
+
+ argc -= optind;
+ argv += optind;
+
+ if (!argc && !server)
+ ibdiag_show_usage();
+
+ if (argc > 1 && (attr = match_attr(argv[1])) < 0)
+ ibdiag_show_usage();
+
+ srcport = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 3);
+ if (!srcport)
+ IBEXIT("Failed to open '%s' port '%d'", ibd_ca, ibd_ca_port);
+
+ if (server) {
+ if (mad_register_server_via(sysstat_class, 1, 0, oui, srcport) <
+ 0)
+ IBEXIT("can't serve class %d", sysstat_class);
+
+ host_ncpu = build_cpuinfo();
+
+ if ((err = ibsystat_serv()))
+ IBEXIT("ibssystat to %s: %s", portid2str(&portid),
+ err);
+ exit(0);
+ }
+
+ if (mad_register_client_via(sysstat_class, 1, srcport) < 0)
+ IBEXIT("can't register to sysstat class %d", sysstat_class);
+
+ if (with_grh && ibd_dest_type != IB_DEST_LID)
+ IBEXIT("When using GRH, LID should be provided");
+ if (resolve_portid_str(ibd_ca, ibd_ca_port, &portid, argv[0],
+ ibd_dest_type, ibd_sm_id, srcport) < 0)
+ IBEXIT("can't resolve destination port %s", argv[0]);
+ if (with_grh) {
+ portid.grh_present = 1;
+ memcpy(&portid.gid, &dgid, sizeof(portid.gid));
+ }
+
+ if ((err = ibsystat(&portid, attr)))
+ IBEXIT("ibsystat to %s: %s", portid2str(&portid), err);
+
+ mad_rpc_close_port(srcport);
+ exit(0);
+}
diff --git a/contrib/ofed/infiniband-diags/src/ibtracert.c b/contrib/ofed/infiniband-diags/src/ibtracert.c
new file mode 100644
index 000000000000..1da3d62a5cc6
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/src/ibtracert.c
@@ -0,0 +1,881 @@
+/*
+ * Copyright (c) 2004-2009 Voltaire Inc. All rights reserved.
+ * Copyright (c) 2009 HNR Consulting. All rights reserved.
+ * Copyright (c) 2010,2011 Mellanox Technologies LTD. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <getopt.h>
+#include <netinet/in.h>
+#include <inttypes.h>
+
+#include <infiniband/umad.h>
+#include <infiniband/mad.h>
+#include <complib/cl_nodenamemap.h>
+
+#include "ibdiag_common.h"
+
+struct ibmad_port *srcport;
+
+#define MAXHOPS 63
+
+static char *node_type_str[] = {
+ "???",
+ "ca",
+ "switch",
+ "router",
+ "iwarp rnic"
+};
+
+static int timeout = 0; /* ms */
+static int force;
+static FILE *f;
+
+static char *node_name_map_file = NULL;
+static nn_map_t *node_name_map = NULL;
+
+typedef struct Port Port;
+typedef struct Switch Switch;
+typedef struct Node Node;
+
+struct Port {
+ Port *next;
+ Port *remoteport;
+ uint64_t portguid;
+ int portnum;
+ int lid;
+ int lmc;
+ int state;
+ int physstate;
+ char portinfo[64];
+};
+
+struct Switch {
+ int linearcap;
+ int mccap;
+ int linearFDBtop;
+ int fdb_base;
+ int enhsp0;
+ int8_t fdb[64];
+ char switchinfo[64];
+};
+
+struct Node {
+ Node *htnext;
+ Node *dnext;
+ Port *ports;
+ ib_portid_t path;
+ int type;
+ int dist;
+ int numports;
+ int upport;
+ Node *upnode;
+ uint64_t nodeguid; /* also portguid */
+ char nodedesc[64];
+ char nodeinfo[64];
+};
+
+Node *nodesdist[MAXHOPS];
+uint64_t target_portguid;
+
+/*
+ * is_port_inactive
+ * Checks whether or not the port state is other than active.
+ * The "sw" argument is only relevant when the port is on a
+ * switch; for HCAs and routers, this argument is ignored.
+ * Returns 1 when port is not active and 0 when active.
+ * Base switch port 0 is considered always active.
+ */
+static int is_port_inactive(Node * node, Port * port, Switch * sw)
+{
+ int res = 0;
+ if (port->state != 4 &&
+ (node->type != IB_NODE_SWITCH ||
+ (node->type == IB_NODE_SWITCH && sw->enhsp0)))
+ res = 1;
+ return res;
+}
+
+static int get_node(Node * node, Port * port, ib_portid_t * portid)
+{
+ void *pi = port->portinfo, *ni = node->nodeinfo, *nd = node->nodedesc;
+ char *s, *e;
+
+ memset(ni, 0, sizeof(node->nodeinfo));
+ if (!smp_query_via(ni, portid, IB_ATTR_NODE_INFO, 0, timeout, srcport))
+ return -1;
+
+ memset(nd, 0, sizeof(node->nodedesc));
+ if (!smp_query_via(nd, portid, IB_ATTR_NODE_DESC, 0, timeout, srcport))
+ return -1;
+
+ for (s = nd, e = s + 64; s < e; s++) {
+ if (!*s)
+ break;
+ if (!isprint(*s))
+ *s = ' ';
+ }
+
+ memset(pi, 0, sizeof(port->portinfo));
+ if (!smp_query_via(pi, portid, IB_ATTR_PORT_INFO, 0, timeout, srcport))
+ return -1;
+
+ mad_decode_field(ni, IB_NODE_GUID_F, &node->nodeguid);
+ mad_decode_field(ni, IB_NODE_TYPE_F, &node->type);
+ mad_decode_field(ni, IB_NODE_NPORTS_F, &node->numports);
+
+ mad_decode_field(ni, IB_NODE_PORT_GUID_F, &port->portguid);
+ mad_decode_field(ni, IB_NODE_LOCAL_PORT_F, &port->portnum);
+ mad_decode_field(pi, IB_PORT_LID_F, &port->lid);
+ mad_decode_field(pi, IB_PORT_LMC_F, &port->lmc);
+ mad_decode_field(pi, IB_PORT_STATE_F, &port->state);
+
+ DEBUG("portid %s: got node %" PRIx64 " '%s'", portid2str(portid),
+ node->nodeguid, node->nodedesc);
+ return 0;
+}
+
+static int switch_lookup(Switch * sw, ib_portid_t * portid, int lid)
+{
+ void *si = sw->switchinfo, *fdb = sw->fdb;
+
+ memset(si, 0, sizeof(sw->switchinfo));
+ if (!smp_query_via(si, portid, IB_ATTR_SWITCH_INFO, 0, timeout,
+ srcport))
+ return -1;
+
+ mad_decode_field(si, IB_SW_LINEAR_FDB_CAP_F, &sw->linearcap);
+ mad_decode_field(si, IB_SW_LINEAR_FDB_TOP_F, &sw->linearFDBtop);
+ mad_decode_field(si, IB_SW_ENHANCED_PORT0_F, &sw->enhsp0);
+
+ if (lid >= sw->linearcap && lid > sw->linearFDBtop)
+ return -1;
+
+ memset(fdb, 0, sizeof(sw->fdb));
+ if (!smp_query_via(fdb, portid, IB_ATTR_LINEARFORWTBL, lid / 64,
+ timeout, srcport))
+ return -1;
+
+ DEBUG("portid %s: forward lid %d to port %d",
+ portid2str(portid), lid, sw->fdb[lid % 64]);
+ return sw->fdb[lid % 64];
+}
+
+static int sameport(Port * a, Port * b)
+{
+ return a->portguid == b->portguid || (force && a->lid == b->lid);
+}
+
+static int extend_dpath(ib_dr_path_t * path, int nextport)
+{
+ if (path->cnt + 2 >= sizeof(path->p))
+ return -1;
+ ++path->cnt;
+ path->p[path->cnt] = (uint8_t) nextport;
+ return path->cnt;
+}
+
+static void dump_endnode(int dump, char *prompt, Node * node, Port * port)
+{
+ char *nodename = NULL;
+
+ if (!dump)
+ return;
+ if (dump == 1) {
+ fprintf(f, "%s {0x%016" PRIx64 "}[%d]\n",
+ prompt, node->nodeguid,
+ node->type == IB_NODE_SWITCH ? 0 : port->portnum);
+ return;
+ }
+
+ nodename =
+ remap_node_name(node_name_map, node->nodeguid, node->nodedesc);
+
+ fprintf(f, "%s %s {0x%016" PRIx64 "} portnum %d lid %u-%u \"%s\"\n",
+ prompt,
+ (node->type <= IB_NODE_MAX ? node_type_str[node->type] : "???"),
+ node->nodeguid,
+ node->type == IB_NODE_SWITCH ? 0 : port->portnum, port->lid,
+ port->lid + (1 << port->lmc) - 1, nodename);
+
+ free(nodename);
+}
+
+static void dump_route(int dump, Node * node, int outport, Port * port)
+{
+ char *nodename = NULL;
+
+ if (!dump && !ibverbose)
+ return;
+
+ nodename =
+ remap_node_name(node_name_map, node->nodeguid, node->nodedesc);
+
+ if (dump == 1)
+ fprintf(f, "[%d] -> {0x%016" PRIx64 "}[%d]\n",
+ outport, port->portguid, port->portnum);
+ else
+ fprintf(f, "[%d] -> %s port {0x%016" PRIx64
+ "}[%d] lid %u-%u \"%s\"\n", outport,
+ (node->type <=
+ IB_NODE_MAX ? node_type_str[node->type] : "???"),
+ port->portguid, port->portnum, port->lid,
+ port->lid + (1 << port->lmc) - 1, nodename);
+
+ free(nodename);
+}
+
+static int find_route(ib_portid_t * from, ib_portid_t * to, int dump)
+{
+ Node *node, fromnode, tonode, nextnode;
+ Port *port, fromport, toport, nextport;
+ Switch sw;
+ int maxhops = MAXHOPS;
+ int portnum, outport = 255, next_sw_outport = 255;
+
+ memset(&fromnode,0,sizeof(Node));
+ memset(&tonode,0,sizeof(Node));
+ memset(&nextnode,0,sizeof(Node));
+ memset(&fromport,0,sizeof(Port));
+ memset(&toport,0,sizeof(Port));
+ memset(&nextport,0,sizeof(Port));
+
+ DEBUG("from %s", portid2str(from));
+
+ if (get_node(&fromnode, &fromport, from) < 0 ||
+ get_node(&tonode, &toport, to) < 0) {
+ IBWARN("can't reach to/from ports");
+ if (!force)
+ return -1;
+ if (to->lid > 0)
+ toport.lid = to->lid;
+ IBWARN("Force: look for lid %d", to->lid);
+ }
+
+ node = &fromnode;
+ port = &fromport;
+ portnum = port->portnum;
+
+ dump_endnode(dump, "From", node, port);
+ if (node->type == IB_NODE_SWITCH) {
+ next_sw_outport = switch_lookup(&sw, from, to->lid);
+ if (next_sw_outport < 0 || next_sw_outport > node->numports) {
+ /* Need to print the port in badtbl */
+ outport = next_sw_outport;
+ goto badtbl;
+ }
+ }
+
+ while (maxhops--) {
+ if (is_port_inactive(node, port, &sw))
+ goto badport;
+
+ if (sameport(port, &toport))
+ break; /* found */
+
+ if (node->type == IB_NODE_SWITCH) {
+ DEBUG("switch node");
+ outport = next_sw_outport;
+
+ if (extend_dpath(&from->drpath, outport) < 0)
+ goto badpath;
+
+ if (get_node(&nextnode, &nextport, from) < 0) {
+ IBWARN("can't reach port at %s",
+ portid2str(from));
+ return -1;
+ }
+ if (outport == 0) {
+ if (!sameport(&nextport, &toport))
+ goto badtbl;
+ else
+ break; /* found SMA port */
+ }
+ } else if ((node->type == IB_NODE_CA) ||
+ (node->type == IB_NODE_ROUTER)) {
+ int ca_src = 0;
+
+ outport = portnum;
+ DEBUG("ca or router node");
+ if (!sameport(port, &fromport)) {
+ IBWARN
+ ("can't continue: reached CA or router port %"
+ PRIx64 ", lid %d", port->portguid,
+ port->lid);
+ return -1;
+ }
+ /* we are at CA or router "from" - go one hop back to (hopefully) a switch */
+ if (from->drpath.cnt > 0) {
+ DEBUG("ca or router node - return back 1 hop");
+ from->drpath.cnt--;
+ } else {
+ ca_src = 1;
+ if (portnum
+ && extend_dpath(&from->drpath, portnum) < 0)
+ goto badpath;
+ }
+ if (get_node(&nextnode, &nextport, from) < 0) {
+ IBWARN("can't reach port at %s",
+ portid2str(from));
+ return -1;
+ }
+ /* fix port num to be seen from the CA or router side */
+ if (!ca_src)
+ nextport.portnum =
+ from->drpath.p[from->drpath.cnt + 1];
+ }
+ /* only if the next node is a switch, get switch info */
+ if (nextnode.type == IB_NODE_SWITCH) {
+ next_sw_outport = switch_lookup(&sw, from, to->lid);
+ if (next_sw_outport < 0 ||
+ next_sw_outport > nextnode.numports) {
+ /* needed to print the port in badtbl */
+ outport = next_sw_outport;
+ goto badtbl;
+ }
+ }
+
+ port = &nextport;
+ if (is_port_inactive(&nextnode, port, &sw))
+ goto badoutport;
+ node = &nextnode;
+ portnum = port->portnum;
+ dump_route(dump, node, outport, port);
+ }
+
+ if (maxhops <= 0) {
+ IBWARN("no route found after %d hops", MAXHOPS);
+ return -1;
+ }
+ dump_endnode(dump, "To", node, port);
+ return 0;
+
+badport:
+ IBWARN("Bad port state found: node \"%s\" port %d state %d",
+ clean_nodedesc(node->nodedesc), portnum, port->state);
+ return -1;
+badoutport:
+ IBWARN("Bad out port state found: node \"%s\" outport %d state %d",
+ clean_nodedesc(node->nodedesc), outport, port->state);
+ return -1;
+badtbl:
+ IBWARN
+ ("Bad forwarding table entry found at: node \"%s\" lid entry %d is %d (top %d)",
+ clean_nodedesc(node->nodedesc), to->lid, outport, sw.linearFDBtop);
+ return -1;
+badpath:
+ IBWARN("Direct path too long!");
+ return -1;
+}
+
+/**************************
+ * MC span part
+ */
+
+#define HASHGUID(guid) ((uint32_t)(((uint32_t)(guid) * 101) ^ ((uint32_t)((guid) >> 32) * 103)))
+#define HTSZ 137
+
+static int insert_node(Node * new)
+{
+ static Node *nodestbl[HTSZ];
+ int hash = HASHGUID(new->nodeguid) % HTSZ;
+ Node *node;
+
+ for (node = nodestbl[hash]; node; node = node->htnext)
+ if (node->nodeguid == new->nodeguid) {
+ DEBUG("node %" PRIx64 " already exists", new->nodeguid);
+ return -1;
+ }
+
+ new->htnext = nodestbl[hash];
+ nodestbl[hash] = new;
+
+ return 0;
+}
+
+static int get_port(Port * port, int portnum, ib_portid_t * portid)
+{
+ char portinfo[64] = { 0 };
+ void *pi = portinfo;
+
+ port->portnum = portnum;
+
+ if (!smp_query_via(pi, portid, IB_ATTR_PORT_INFO, portnum, timeout,
+ srcport))
+ return -1;
+
+ mad_decode_field(pi, IB_PORT_LID_F, &port->lid);
+ mad_decode_field(pi, IB_PORT_LMC_F, &port->lmc);
+ mad_decode_field(pi, IB_PORT_STATE_F, &port->state);
+ mad_decode_field(pi, IB_PORT_PHYS_STATE_F, &port->physstate);
+
+ VERBOSE("portid %s portnum %d: lid %d state %d physstate %d",
+ portid2str(portid), portnum, port->lid, port->state,
+ port->physstate);
+ return 1;
+}
+
+static void link_port(Port * port, Node * node)
+{
+ port->next = node->ports;
+ node->ports = port;
+}
+
+static int new_node(Node * node, Port * port, ib_portid_t * path, int dist)
+{
+ if (port->portguid == target_portguid) {
+ node->dist = -1; /* tag as target */
+ link_port(port, node);
+ dump_endnode(ibverbose, "found target", node, port);
+ return 1; /* found; */
+ }
+
+ /* BFS search start with my self */
+ if (insert_node(node) < 0)
+ return -1; /* known switch */
+
+ VERBOSE("insert dist %d node %p port %d lid %d", dist, node,
+ port->portnum, port->lid);
+
+ link_port(port, node);
+
+ node->dist = dist;
+ node->path = *path;
+ node->dnext = nodesdist[dist];
+ nodesdist[dist] = node;
+
+ return 0;
+}
+
+static int switch_mclookup(Node * node, ib_portid_t * portid, int mlid,
+ char *map)
+{
+ Switch sw;
+ char mdb[64];
+ void *si = sw.switchinfo;
+ uint16_t *msets = (uint16_t *) mdb;
+ int maxsets, block, i, set;
+
+ memset(map, 0, 256);
+
+ memset(si, 0, sizeof(sw.switchinfo));
+ if (!smp_query_via(si, portid, IB_ATTR_SWITCH_INFO, 0, timeout,
+ srcport))
+ return -1;
+
+ mlid -= 0xc000;
+
+ mad_decode_field(si, IB_SW_MCAST_FDB_CAP_F, &sw.mccap);
+
+ if (mlid >= sw.mccap)
+ return -1;
+
+ block = mlid / 32;
+ maxsets = (node->numports + 15) / 16; /* round up */
+
+ for (set = 0; set < maxsets; set++) {
+ memset(mdb, 0, sizeof(mdb));
+ if (!smp_query_via(mdb, portid, IB_ATTR_MULTICASTFORWTBL,
+ block | (set << 28), timeout, srcport))
+ return -1;
+
+ for (i = 0; i < 16; i++, map++) {
+ uint16_t mask = ntohs(msets[mlid % 32]);
+ if (mask & (1 << i))
+ *map = 1;
+ else
+ continue;
+ VERBOSE("Switch guid 0x%" PRIx64
+ ": mlid 0x%x is forwarded to port %d",
+ node->nodeguid, mlid + 0xc000, i + set * 16);
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Return 1 if found, 0 if not, -1 on errors.
+ */
+static Node *find_mcpath(ib_portid_t * from, int mlid)
+{
+ Node *node, *remotenode;
+ Port *port, *remoteport;
+ char map[256];
+ int r, i;
+ int dist = 0, leafport = 0;
+ ib_portid_t *path;
+
+ DEBUG("from %s", portid2str(from));
+
+ if (!(node = calloc(1, sizeof(Node))))
+ IBEXIT("out of memory");
+
+ if (!(port = calloc(1, sizeof(Port))))
+ IBEXIT("out of memory");
+
+ if (get_node(node, port, from) < 0) {
+ IBWARN("can't reach node %s", portid2str(from));
+ return 0;
+ }
+
+ node->upnode = 0; /* root */
+ if ((r = new_node(node, port, from, 0)) > 0) {
+ if (node->type != IB_NODE_SWITCH) {
+ IBWARN("ibtracert from CA to CA is unsupported");
+ return 0; /* ibtracert from host to itself is unsupported */
+ }
+
+ if (switch_mclookup(node, from, mlid, map) < 0 || !map[0])
+ return 0;
+ return node;
+ }
+
+ for (dist = 0; dist < MAXHOPS; dist++) {
+
+ for (node = nodesdist[dist]; node; node = node->dnext) {
+
+ path = &node->path;
+
+ VERBOSE("dist %d node %p", dist, node);
+ dump_endnode(ibverbose, "processing", node,
+ node->ports);
+
+ memset(map, 0, sizeof(map));
+
+ if (node->type != IB_NODE_SWITCH) {
+ if (dist)
+ continue;
+ leafport = path->drpath.p[path->drpath.cnt];
+ map[port->portnum] = 1;
+ node->upport = 0; /* starting here */
+ DEBUG("Starting from CA 0x%" PRIx64
+ " lid %d port %d (leafport %d)",
+ node->nodeguid, port->lid, port->portnum,
+ leafport);
+ } else { /* switch */
+
+ /* if starting from a leaf port fix up port (up port) */
+ if (dist == 1 && leafport)
+ node->upport = leafport;
+
+ if (switch_mclookup(node, path, mlid, map) < 0) {
+ IBWARN("skipping bad Switch 0x%" PRIx64
+ "", node->nodeguid);
+ continue;
+ }
+ }
+
+ for (i = 1; i <= node->numports; i++) {
+ if (!map[i] || i == node->upport)
+ continue;
+
+ if (dist == 0 && leafport) {
+ if (from->drpath.cnt > 0)
+ path->drpath.cnt--;
+ } else {
+ if (!(port = calloc(1, sizeof(Port))))
+ IBEXIT("out of memory");
+
+ if (get_port(port, i, path) < 0) {
+ IBWARN
+ ("can't reach node %s port %d",
+ portid2str(path), i);
+ free(port);
+ return 0;
+ }
+
+ if (port->physstate != 5) { /* LinkUP */
+ free(port);
+ continue;
+ }
+#if 0
+ link_port(port, node);
+#endif
+
+ if (extend_dpath(&path->drpath, i) < 0) {
+ free(port);
+ return 0;
+ }
+ }
+
+ if (!(remotenode = calloc(1, sizeof(Node))))
+ IBEXIT("out of memory");
+
+ if (!(remoteport = calloc(1, sizeof(Port))))
+ IBEXIT("out of memory");
+
+ if (get_node(remotenode, remoteport, path) < 0) {
+ IBWARN
+ ("NodeInfo on %s port %d failed, skipping port",
+ portid2str(path), i);
+ path->drpath.cnt--; /* restore path */
+ free(remotenode);
+ free(remoteport);
+ continue;
+ }
+
+ remotenode->upnode = node;
+ remotenode->upport = remoteport->portnum;
+ remoteport->remoteport = port;
+
+ if ((r = new_node(remotenode, remoteport, path,
+ dist + 1)) > 0)
+ return remotenode;
+
+ if (r == 0)
+ dump_endnode(ibverbose, "new remote",
+ remotenode, remoteport);
+ else if (remotenode->type == IB_NODE_SWITCH)
+ dump_endnode(2,
+ "ERR: circle discovered at",
+ remotenode, remoteport);
+
+ path->drpath.cnt--; /* restore path */
+ }
+ }
+ }
+
+ return 0; /* not found */
+}
+
+static uint64_t find_target_portguid(ib_portid_t * to)
+{
+ Node tonode;
+ Port toport;
+
+ if (get_node(&tonode, &toport, to) < 0) {
+ IBWARN("can't find to port\n");
+ return -1;
+ }
+
+ return toport.portguid;
+}
+
+static void dump_mcpath(Node * node, int dumplevel)
+{
+ char *nodename = NULL;
+
+ if (node->upnode)
+ dump_mcpath(node->upnode, dumplevel);
+
+ nodename =
+ remap_node_name(node_name_map, node->nodeguid, node->nodedesc);
+
+ if (!node->dist) {
+ printf("From %s 0x%" PRIx64 " port %d lid %u-%u \"%s\"\n",
+ (node->type <=
+ IB_NODE_MAX ? node_type_str[node->type] : "???"),
+ node->nodeguid, node->ports->portnum, node->ports->lid,
+ node->ports->lid + (1 << node->ports->lmc) - 1,
+ nodename);
+ goto free_name;
+ }
+
+ if (node->dist) {
+ if (dumplevel == 1)
+ printf("[%d] -> %s {0x%016" PRIx64 "}[%d]\n",
+ node->ports->remoteport->portnum,
+ (node->type <=
+ IB_NODE_MAX ? node_type_str[node->type] :
+ "???"), node->nodeguid, node->upport);
+ else
+ printf("[%d] -> %s 0x%" PRIx64 "[%d] lid %u \"%s\"\n",
+ node->ports->remoteport->portnum,
+ (node->type <=
+ IB_NODE_MAX ? node_type_str[node->type] :
+ "???"), node->nodeguid, node->upport,
+ node->ports->lid, nodename);
+ }
+
+ if (node->dist < 0)
+ /* target node */
+ printf("To %s 0x%" PRIx64 " port %d lid %u-%u \"%s\"\n",
+ (node->type <=
+ IB_NODE_MAX ? node_type_str[node->type] : "???"),
+ node->nodeguid, node->ports->portnum, node->ports->lid,
+ node->ports->lid + (1 << node->ports->lmc) - 1,
+ nodename);
+
+free_name:
+ free(nodename);
+}
+
+static int resolve_lid(ib_portid_t * portid, const void *srcport)
+{
+ uint8_t portinfo[64] = { 0 };
+ uint16_t lid;
+
+ if (!smp_query_via(portinfo, portid, IB_ATTR_PORT_INFO, 0, 0, srcport))
+ return -1;
+ mad_decode_field(portinfo, IB_PORT_LID_F, &lid);
+
+ ib_portid_set(portid, lid, 0, 0);
+
+ return 0;
+}
+
+static int dumplevel = 2, multicast, mlid;
+
+static int process_opt(void *context, int ch, char *optarg)
+{
+ switch (ch) {
+ case 1:
+ node_name_map_file = strdup(optarg);
+ break;
+ case 'm':
+ multicast++;
+ mlid = strtoul(optarg, 0, 0);
+ break;
+ case 'f':
+ force++;
+ break;
+ case 'n':
+ dumplevel = 1;
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ int mgmt_classes[3] =
+ { IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS };
+ ib_portid_t my_portid = { 0 };
+ ib_portid_t src_portid = { 0 };
+ ib_portid_t dest_portid = { 0 };
+ Node *endnode;
+
+ const struct ibdiag_opt opts[] = {
+ {"force", 'f', 0, NULL, "force"},
+ {"no_info", 'n', 0, NULL, "simple format"},
+ {"mlid", 'm', 1, "<mlid>", "multicast trace of the mlid"},
+ {"node-name-map", 1, 1, "<file>", "node name map file"},
+ {0}
+ };
+ char usage_args[] = "<src-addr> <dest-addr>";
+ const char *usage_examples[] = {
+ "- Unicast examples:",
+ "4 16\t\t\t# show path between lids 4 and 16",
+ "-n 4 16\t\t# same, but using simple output format",
+ "-G 0x8f1040396522d 0x002c9000100d051\t# use guid addresses",
+
+ " - Multicast examples:",
+ "-m 0xc000 4 16\t# show multicast path of mlid 0xc000 between lids 4 and 16",
+ NULL,
+ };
+
+ ibdiag_process_opts(argc, argv, NULL, "DK", opts, process_opt,
+ usage_args, usage_examples);
+
+ f = stdout;
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 2)
+ ibdiag_show_usage();
+
+ if (ibd_timeout)
+ timeout = ibd_timeout;
+
+ srcport = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 3);
+ if (!srcport)
+ IBEXIT("Failed to open '%s' port '%d'", ibd_ca, ibd_ca_port);
+
+ smp_mkey_set(srcport, ibd_mkey);
+
+ node_name_map = open_node_name_map(node_name_map_file);
+
+ if (resolve_portid_str(ibd_ca, ibd_ca_port, &src_portid, argv[0],
+ ibd_dest_type, ibd_sm_id, srcport) < 0)
+ IBEXIT("can't resolve source port %s", argv[0]);
+
+ if (resolve_portid_str(ibd_ca, ibd_ca_port, &dest_portid, argv[1],
+ ibd_dest_type, ibd_sm_id, srcport) < 0)
+ IBEXIT("can't resolve destination port %s", argv[1]);
+
+ if (ibd_dest_type == IB_DEST_DRPATH) {
+ if (resolve_lid(&src_portid, NULL) < 0)
+ IBEXIT("cannot resolve lid for port \'%s\'",
+ portid2str(&src_portid));
+ if (resolve_lid(&dest_portid, NULL) < 0)
+ IBEXIT("cannot resolve lid for port \'%s\'",
+ portid2str(&dest_portid));
+ }
+
+ if (dest_portid.lid == 0 || src_portid.lid == 0) {
+ IBWARN("bad src/dest lid");
+ ibdiag_show_usage();
+ }
+
+ if (ibd_dest_type != IB_DEST_DRPATH) {
+ /* first find a direct path to the src port */
+ if (find_route(&my_portid, &src_portid, 0) < 0)
+ IBEXIT("can't find a route to the src port");
+
+ src_portid = my_portid;
+ }
+
+ if (!multicast) {
+ if (find_route(&src_portid, &dest_portid, dumplevel) < 0)
+ IBEXIT("can't find a route from src to dest");
+ exit(0);
+ } else {
+ if (mlid < 0xc000)
+ IBWARN("invalid MLID; must be 0xc000 or larger");
+ }
+
+ if (!(target_portguid = find_target_portguid(&dest_portid)))
+ IBEXIT("can't reach target lid %d", dest_portid.lid);
+
+ if (!(endnode = find_mcpath(&src_portid, mlid)))
+ IBEXIT("can't find a multicast route from src to dest");
+
+ /* dump multicast path */
+ dump_mcpath(endnode, dumplevel);
+
+ close_node_name_map(node_name_map);
+
+ mad_rpc_close_port(srcport);
+
+ exit(0);
+}
diff --git a/contrib/ofed/infiniband-diags/src/mcm_rereg_test.c b/contrib/ofed/infiniband-diags/src/mcm_rereg_test.c
new file mode 100644
index 000000000000..a8cce8b49d75
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/src/mcm_rereg_test.c
@@ -0,0 +1,399 @@
+/*
+ * Copyright (c) 2006-2009 Voltaire, Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <inttypes.h>
+
+#include <infiniband/umad.h>
+#include <infiniband/mad.h>
+#include <infiniband/iba/ib_types.h>
+
+#include "ibdiag_common.h"
+
+#define info(fmt, ...) fprintf(stderr, "INFO: " fmt, ## __VA_ARGS__ )
+#define err(fmt, ...) fprintf(stderr, "ERR: " fmt, ## __VA_ARGS__ )
+#ifdef NOISY_DEBUG
+#define dbg(fmt, ...) fprintf(stderr, "DBG: " fmt, ## __VA_ARGS__ )
+#else
+#define dbg(fmt, ...)
+#endif
+
+#define TMO 100
+
+static ibmad_gid_t mgid_ipoib = {
+ 0xff, 0x12, 0x40, 0x1b, 0xff, 0xff, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff
+};
+
+struct ibmad_port *srcport;
+
+uint64_t build_mcm_rec(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, 1);
+
+ return IB_MCR_COMPMASK_MGID | IB_MCR_COMPMASK_PORT_GID |
+ IB_MCR_COMPMASK_JOIN_STATE;
+}
+
+static void build_mcm_rec_umad(void *umad, ib_portid_t * dport, int method,
+ uint64_t comp_mask, uint8_t * data)
+{
+ ib_rpc_t rpc;
+
+ memset(&rpc, 0, sizeof(rpc));
+ rpc.mgtclass = IB_SA_CLASS;
+ rpc.method = method;
+ rpc.attr.id = IB_SA_ATTR_MCRECORD;
+ rpc.attr.mod = 0; // ???
+ rpc.mask = comp_mask;
+ rpc.datasz = IB_SA_DATA_SIZE;
+ rpc.dataoffs = IB_SA_DATA_OFFS;
+
+ mad_build_pkt(umad, &rpc, dport, NULL, data);
+}
+
+static int rereg_send(int port, int agent, ib_portid_t * dport,
+ uint8_t * umad, int len, int method, ibmad_gid_t port_gid)
+{
+ uint8_t data[IB_SA_DATA_SIZE];
+ uint64_t comp_mask;
+
+ comp_mask = build_mcm_rec(data, mgid_ipoib, port_gid);
+
+ build_mcm_rec_umad(umad, dport, method, comp_mask, data);
+ if (umad_send(port, agent, umad, len, TMO, 0) < 0) {
+ err("umad_send %s failed: %s\n",
+ (method == IB_MAD_METHOD_GET) ? "query" : "non query",
+ strerror(errno));
+ return -1;
+ }
+ dbg("umad_send %d: tid = 0x%016" PRIx64 "\n", method,
+ mad_get_field64(umad_get_mad(umad), 0, IB_MAD_TRID_F));
+
+ return 0;
+}
+
+static int rereg_port_gid(int port, int agent, ib_portid_t * dport,
+ uint8_t * umad, int len, ibmad_gid_t port_gid)
+{
+ uint8_t data[IB_SA_DATA_SIZE];
+ uint64_t comp_mask;
+
+ comp_mask = build_mcm_rec(data, mgid_ipoib, port_gid);
+
+ build_mcm_rec_umad(umad, dport, IB_MAD_METHOD_DELETE, comp_mask, data);
+ if (umad_send(port, agent, umad, len, TMO, 0) < 0) {
+ err("umad_send leave failed: %s\n", strerror(errno));
+ return -1;
+ }
+ dbg("umad_send leave: tid = 0x%016" PRIx64 "\n",
+ mad_get_field64(umad_get_mad(umad), 0, IB_MAD_TRID_F));
+
+ build_mcm_rec_umad(umad, dport, IB_MAD_METHOD_SET, comp_mask, data);
+ if (umad_send(port, agent, umad, len, TMO, 0) < 0) {
+ err("umad_send join failed: %s\n", strerror(errno));
+ return -1;
+ }
+ dbg("umad_send join: tid = 0x%016" PRIx64 "\n",
+ mad_get_field64(umad_get_mad(umad), 0, IB_MAD_TRID_F));
+
+ return 0;
+}
+
+struct guid_trid {
+ ibmad_gid_t gid;
+ uint64_t guid;
+ uint64_t trid;
+};
+
+static int rereg_send_all(int port, int agent, ib_portid_t * dport,
+ struct guid_trid *list, unsigned cnt)
+{
+ uint8_t *umad;
+ int len = umad_size() + 256;
+ unsigned i;
+ int ret;
+
+ info("rereg_send_all... cnt = %u\n", cnt);
+
+ umad = calloc(1, len);
+ if (!umad) {
+ err("cannot alloc mem for umad: %s\n", strerror(errno));
+ return -1;
+ }
+
+ for (i = 0; i < cnt; i++) {
+ ret =
+ rereg_port_gid(port, agent, dport, umad, len, list[i].gid);
+ if (ret < 0) {
+ err("rereg_send_all: rereg_port_gid 0x%016" PRIx64
+ " failed\n", ntohll(list[i].guid));
+ continue;
+ }
+ list[i].trid = mad_get_field64(umad_get_mad(umad), 0,
+ IB_MAD_TRID_F);
+ }
+
+ info("rereg_send_all: sent %u requests\n", cnt * 2);
+
+ free(umad);
+
+ return 0;
+}
+
+static int rereg_recv(int port, int agent, ib_portid_t * dport,
+ uint8_t * umad, int length, int tmo)
+{
+ int ret, retry = 0;
+ int len = length;
+
+ while ((ret = umad_recv(port, umad, &len, tmo)) < 0 &&
+ errno == ETIMEDOUT) {
+ if (retry++ > 3)
+ return 0;
+ }
+ if (ret < 0) {
+ err("umad_recv %d failed: %s\n", ret, strerror(errno));
+ return -1;
+ }
+ dbg("umad_recv (retries %d), tid = 0x%016" PRIx64
+ ": len = %d, status = %d\n", retry,
+ mad_get_field64(umad_get_mad(umad), 0, IB_MAD_TRID_F), len,
+ umad_status(umad));
+
+ return 1;
+}
+
+static int rereg_recv_all(int port, int agent, ib_portid_t * dport,
+ struct guid_trid *list, unsigned cnt)
+{
+ uint8_t *umad, *mad;
+ int len = umad_size() + 256;
+ uint64_t trid;
+ unsigned n, method, status;
+ unsigned i;
+
+ info("rereg_recv_all...\n");
+
+ umad = calloc(1, len);
+ if (!umad) {
+ err("cannot alloc mem for umad: %s\n", strerror(errno));
+ return -1;
+ }
+
+ n = 0;
+ while (rereg_recv(port, agent, dport, umad, len, TMO) > 0) {
+ dbg("rereg_recv_all: done %d\n", n);
+ n++;
+ mad = umad_get_mad(umad);
+
+ method = mad_get_field(mad, 0, IB_MAD_METHOD_F);
+ status = mad_get_field(mad, 0, IB_MAD_STATUS_F);
+
+ if (status)
+ dbg("MAD status %x, method %x\n", status, method);
+
+ if (status &&
+ (method & 0x7f) == (IB_MAD_METHOD_GET_RESPONSE & 0x7f)) {
+ trid = mad_get_field64(mad, 0, IB_MAD_TRID_F);
+ for (i = 0; i < cnt; i++)
+ if (trid == list[i].trid)
+ break;
+ if (i == cnt) {
+ err("cannot find trid 0x%016" PRIx64 "\n",
+ trid);
+ continue;
+ }
+ info("guid 0x%016" PRIx64
+ ": method = %x status = %x. Resending\n",
+ ntohll(list[i].guid), method, status);
+ rereg_port_gid(port, agent, dport, umad, len,
+ list[i].gid);
+ list[i].trid =
+ mad_get_field64(umad_get_mad(umad), 0,
+ IB_MAD_TRID_F);
+ }
+ }
+
+ info("rereg_recv_all: got %u responses\n", n);
+
+ free(umad);
+ return 0;
+}
+
+static int rereg_query_all(int port, int agent, ib_portid_t * dport,
+ struct guid_trid *list, unsigned cnt)
+{
+ uint8_t *umad, *mad;
+ int len = umad_size() + 256;
+ unsigned method, status;
+ unsigned i;
+ int ret;
+
+ info("rereg_query_all...\n");
+
+ umad = calloc(1, len);
+ if (!umad) {
+ err("cannot alloc mem for umad: %s\n", strerror(errno));
+ return -1;
+ }
+
+ for (i = 0; i < cnt; i++) {
+ ret = rereg_send(port, agent, dport, umad, len,
+ IB_MAD_METHOD_GET, list[i].gid);
+ if (ret < 0) {
+ err("query_all: rereg_send failed.\n");
+ continue;
+ }
+
+ ret = rereg_recv(port, agent, dport, umad, len, TMO);
+ if (ret < 0) {
+ err("query_all: rereg_recv failed.\n");
+ continue;
+ }
+
+ mad = umad_get_mad(umad);
+
+ method = mad_get_field(mad, 0, IB_MAD_METHOD_F);
+ status = mad_get_field(mad, 0, IB_MAD_STATUS_F);
+
+ if (status)
+ info("guid 0x%016" PRIx64 ": status %x, method %x\n",
+ ntohll(list[i].guid), status, method);
+ }
+
+ info("rereg_query_all: %u queried.\n", cnt);
+
+ free(umad);
+ return 0;
+}
+
+#define MAX_CLIENTS 50
+
+static int rereg_and_test_port(char *guid_file, int port, int agent,
+ ib_portid_t * dport, int timeout)
+{
+ char line[256];
+ FILE *f;
+ ibmad_gid_t port_gid;
+ uint64_t prefix = htonll(0xfe80000000000000ull);
+ uint64_t guid = htonll(0x0002c90200223825ull);
+ struct guid_trid *list;
+ int i = 0;
+
+ list = calloc(MAX_CLIENTS, sizeof(*list));
+ if (!list) {
+ err("cannot alloc mem for guid/trid list: %s\n",
+ strerror(errno));
+ return -1;
+ }
+
+ f = fopen(guid_file, "r");
+ if (!f) {
+ err("cannot open %s: %s\n", guid_file, strerror(errno));
+ return -1;
+ }
+
+ while (fgets(line, sizeof(line), f)) {
+ guid = strtoull(line, NULL, 0);
+ guid = htonll(guid);
+ memcpy(&port_gid[0], &prefix, 8);
+ memcpy(&port_gid[8], &guid, 8);
+
+ list[i].guid = guid;
+ memcpy(list[i].gid, port_gid, sizeof(list[i].gid));
+ list[i].trid = 0;
+ if (++i >= MAX_CLIENTS)
+ break;
+ }
+ fclose(f);
+
+ rereg_send_all(port, agent, dport, list, i);
+ rereg_recv_all(port, agent, dport, list, i);
+
+ rereg_query_all(port, agent, dport, list, i);
+
+ free(list);
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ char *guid_file = "port_guids.list";
+ int mgmt_classes[2] = { IB_SMI_CLASS, IB_SMI_DIRECT_CLASS };
+ ib_portid_t dport_id;
+ int port, agent;
+ uint8_t *umad, *mad;
+ int len;
+
+ if (argc > 1)
+ guid_file = argv[1];
+
+ srcport = mad_rpc_open_port(NULL, 0, mgmt_classes, 2);
+ if (!srcport)
+ err("Failed to open port");
+
+ resolve_sm_portid(NULL, 0, &dport_id);
+ dport_id.qp = 1;
+ if (!dport_id.qkey)
+ dport_id.qkey = IB_DEFAULT_QP1_QKEY;
+
+ len = umad_size() + 256;
+ umad = calloc(1, len);
+ if (!umad) {
+ err("cannot alloc mem for umad: %s\n", strerror(errno));
+ return -1;
+ }
+ port = mad_rpc_portid(srcport);
+
+ agent = umad_register(port, IB_SA_CLASS, 2, 0, NULL);
+
+ rereg_and_test_port(guid_file, port, agent, &dport_id, TMO);
+ mad = umad_get_mad(umad);
+
+ free(umad);
+ umad_unregister(port, agent);
+ umad_close_port(port);
+ umad_done();
+
+ return 0;
+}
diff --git a/contrib/ofed/infiniband-diags/src/perfquery.c b/contrib/ofed/infiniband-diags/src/perfquery.c
new file mode 100644
index 000000000000..55d65de42394
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/src/perfquery.c
@@ -0,0 +1,1122 @@
+/*
+ * Copyright (c) 2004-2009 Voltaire Inc. All rights reserved.
+ * Copyright (c) 2007 Xsigo Systems Inc. All rights reserved.
+ * Copyright (c) 2009 HNR Consulting. All rights reserved.
+ * Copyright (c) 2011 Mellanox Technologies LTD. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <netinet/in.h>
+
+#include <infiniband/umad.h>
+#include <infiniband/mad.h>
+#include <infiniband/iba/ib_types.h>
+
+#include "ibdiag_common.h"
+
+struct ibmad_port *srcport;
+
+static ibmad_gid_t dgid;
+static int with_grh;
+
+struct perf_count {
+ uint32_t portselect;
+ uint32_t counterselect;
+ uint32_t symbolerrors;
+ uint32_t linkrecovers;
+ uint32_t linkdowned;
+ uint32_t rcverrors;
+ uint32_t rcvremotephyerrors;
+ uint32_t rcvswrelayerrors;
+ uint32_t xmtdiscards;
+ uint32_t xmtconstrainterrors;
+ uint32_t rcvconstrainterrors;
+ uint32_t linkintegrityerrors;
+ uint32_t excbufoverrunerrors;
+ uint32_t qp1dropped;
+ uint32_t vl15dropped;
+ uint32_t xmtdata;
+ uint32_t rcvdata;
+ uint32_t xmtpkts;
+ uint32_t rcvpkts;
+ uint32_t xmtwait;
+};
+
+struct perf_count_ext {
+ uint32_t portselect;
+ uint32_t counterselect;
+ uint64_t portxmitdata;
+ uint64_t portrcvdata;
+ uint64_t portxmitpkts;
+ uint64_t portrcvpkts;
+ uint64_t portunicastxmitpkts;
+ uint64_t portunicastrcvpkts;
+ uint64_t portmulticastxmitpkits;
+ uint64_t portmulticastrcvpkts;
+
+ uint32_t counterSelect2;
+ uint64_t symbolErrorCounter;
+ uint64_t linkErrorRecoveryCounter;
+ uint64_t linkDownedCounter;
+ uint64_t portRcvErrors;
+ uint64_t portRcvRemotePhysicalErrors;
+ uint64_t portRcvSwitchRelayErrors;
+ uint64_t portXmitDiscards;
+ uint64_t portXmitConstraintErrors;
+ uint64_t portRcvConstraintErrors;
+ uint64_t localLinkIntegrityErrors;
+ uint64_t excessiveBufferOverrunErrors;
+ uint64_t VL15Dropped;
+ uint64_t portXmitWait;
+ uint64_t QP1Dropped;
+};
+
+static uint8_t pc[1024];
+
+struct perf_count perf_count = {0};
+struct perf_count_ext perf_count_ext = {0};
+
+#define ALL_PORTS 0xFF
+#define MAX_PORTS 255
+
+/* Notes: IB semantics is to cap counters if count has exceeded limits.
+ * Therefore we must check for overflows and cap the counters if necessary.
+ *
+ * mad_decode_field and mad_encode_field assume 32 bit integers passed in
+ * for fields < 32 bits in length.
+ */
+
+static void aggregate_4bit(uint32_t * dest, uint32_t val)
+{
+ if ((((*dest) + val) < (*dest)) || ((*dest) + val) > 0xf)
+ (*dest) = 0xf;
+ else
+ (*dest) = (*dest) + val;
+}
+
+static void aggregate_8bit(uint32_t * dest, uint32_t val)
+{
+ if ((((*dest) + val) < (*dest))
+ || ((*dest) + val) > 0xff)
+ (*dest) = 0xff;
+ else
+ (*dest) = (*dest) + val;
+}
+
+static void aggregate_16bit(uint32_t * dest, uint32_t val)
+{
+ if ((((*dest) + val) < (*dest))
+ || ((*dest) + val) > 0xffff)
+ (*dest) = 0xffff;
+ else
+ (*dest) = (*dest) + val;
+}
+
+static void aggregate_32bit(uint32_t * dest, uint32_t val)
+{
+ if (((*dest) + val) < (*dest))
+ (*dest) = 0xffffffff;
+ else
+ (*dest) = (*dest) + val;
+}
+
+static void aggregate_64bit(uint64_t * dest, uint64_t val)
+{
+ if (((*dest) + val) < (*dest))
+ (*dest) = 0xffffffffffffffffULL;
+ else
+ (*dest) = (*dest) + val;
+}
+
+static void aggregate_perfcounters(void)
+{
+ uint32_t val;
+
+ mad_decode_field(pc, IB_PC_PORT_SELECT_F, &val);
+ perf_count.portselect = val;
+ mad_decode_field(pc, IB_PC_COUNTER_SELECT_F, &val);
+ perf_count.counterselect = val;
+ mad_decode_field(pc, IB_PC_ERR_SYM_F, &val);
+ aggregate_16bit(&perf_count.symbolerrors, val);
+ mad_decode_field(pc, IB_PC_LINK_RECOVERS_F, &val);
+ aggregate_8bit(&perf_count.linkrecovers, val);
+ mad_decode_field(pc, IB_PC_LINK_DOWNED_F, &val);
+ aggregate_8bit(&perf_count.linkdowned, val);
+ mad_decode_field(pc, IB_PC_ERR_RCV_F, &val);
+ aggregate_16bit(&perf_count.rcverrors, val);
+ mad_decode_field(pc, IB_PC_ERR_PHYSRCV_F, &val);
+ aggregate_16bit(&perf_count.rcvremotephyerrors, val);
+ mad_decode_field(pc, IB_PC_ERR_SWITCH_REL_F, &val);
+ aggregate_16bit(&perf_count.rcvswrelayerrors, val);
+ mad_decode_field(pc, IB_PC_XMT_DISCARDS_F, &val);
+ aggregate_16bit(&perf_count.xmtdiscards, val);
+ mad_decode_field(pc, IB_PC_ERR_XMTCONSTR_F, &val);
+ aggregate_8bit(&perf_count.xmtconstrainterrors, val);
+ mad_decode_field(pc, IB_PC_ERR_RCVCONSTR_F, &val);
+ aggregate_8bit(&perf_count.rcvconstrainterrors, val);
+ mad_decode_field(pc, IB_PC_ERR_LOCALINTEG_F, &val);
+ aggregate_4bit(&perf_count.linkintegrityerrors, val);
+ mad_decode_field(pc, IB_PC_ERR_EXCESS_OVR_F, &val);
+ aggregate_4bit(&perf_count.excbufoverrunerrors, val);
+#ifdef HAVE_IB_PC_QP1_DROP_F
+ mad_decode_field(pc, IB_PC_QP1_DROP_F, &val);
+ aggregate_16bit(&perf_count.qp1dropped, val);
+#endif
+ mad_decode_field(pc, IB_PC_VL15_DROPPED_F, &val);
+ aggregate_16bit(&perf_count.vl15dropped, val);
+ mad_decode_field(pc, IB_PC_XMT_BYTES_F, &val);
+ aggregate_32bit(&perf_count.xmtdata, val);
+ mad_decode_field(pc, IB_PC_RCV_BYTES_F, &val);
+ aggregate_32bit(&perf_count.rcvdata, val);
+ mad_decode_field(pc, IB_PC_XMT_PKTS_F, &val);
+ aggregate_32bit(&perf_count.xmtpkts, val);
+ mad_decode_field(pc, IB_PC_RCV_PKTS_F, &val);
+ aggregate_32bit(&perf_count.rcvpkts, val);
+ mad_decode_field(pc, IB_PC_XMT_WAIT_F, &val);
+ aggregate_32bit(&perf_count.xmtwait, val);
+}
+
+static void output_aggregate_perfcounters(ib_portid_t * portid,
+ uint16_t cap_mask)
+{
+ char buf[1024];
+ uint32_t val = ALL_PORTS;
+
+ /* set port_select to 255 to emulate AllPortSelect */
+ mad_encode_field(pc, IB_PC_PORT_SELECT_F, &val);
+ mad_encode_field(pc, IB_PC_COUNTER_SELECT_F, &perf_count.counterselect);
+ mad_encode_field(pc, IB_PC_ERR_SYM_F, &perf_count.symbolerrors);
+ mad_encode_field(pc, IB_PC_LINK_RECOVERS_F, &perf_count.linkrecovers);
+ mad_encode_field(pc, IB_PC_LINK_DOWNED_F, &perf_count.linkdowned);
+ mad_encode_field(pc, IB_PC_ERR_RCV_F, &perf_count.rcverrors);
+ mad_encode_field(pc, IB_PC_ERR_PHYSRCV_F,
+ &perf_count.rcvremotephyerrors);
+ mad_encode_field(pc, IB_PC_ERR_SWITCH_REL_F,
+ &perf_count.rcvswrelayerrors);
+ mad_encode_field(pc, IB_PC_XMT_DISCARDS_F, &perf_count.xmtdiscards);
+ mad_encode_field(pc, IB_PC_ERR_XMTCONSTR_F,
+ &perf_count.xmtconstrainterrors);
+ mad_encode_field(pc, IB_PC_ERR_RCVCONSTR_F,
+ &perf_count.rcvconstrainterrors);
+ mad_encode_field(pc, IB_PC_ERR_LOCALINTEG_F,
+ &perf_count.linkintegrityerrors);
+ mad_encode_field(pc, IB_PC_ERR_EXCESS_OVR_F,
+ &perf_count.excbufoverrunerrors);
+#ifdef HAVE_IB_PC_QP1_DROP_F
+ mad_encode_field(pc, IB_PC_QP1_DROP_F, &perf_count.qp1dropped);
+#endif
+ mad_encode_field(pc, IB_PC_VL15_DROPPED_F, &perf_count.vl15dropped);
+ mad_encode_field(pc, IB_PC_XMT_BYTES_F, &perf_count.xmtdata);
+ mad_encode_field(pc, IB_PC_RCV_BYTES_F, &perf_count.rcvdata);
+ mad_encode_field(pc, IB_PC_XMT_PKTS_F, &perf_count.xmtpkts);
+ mad_encode_field(pc, IB_PC_RCV_PKTS_F, &perf_count.rcvpkts);
+ mad_encode_field(pc, IB_PC_XMT_WAIT_F, &perf_count.xmtwait);
+
+ mad_dump_perfcounters(buf, sizeof buf, pc, sizeof pc);
+
+ printf("# Port counters: %s port %d (CapMask: 0x%02X)\n%s",
+ portid2str(portid), ALL_PORTS, ntohs(cap_mask), buf);
+}
+
+static void aggregate_perfcounters_ext(uint16_t cap_mask, uint32_t cap_mask2)
+{
+ uint32_t val;
+ uint64_t val64;
+
+ mad_decode_field(pc, IB_PC_EXT_PORT_SELECT_F, &val);
+ perf_count_ext.portselect = val;
+ mad_decode_field(pc, IB_PC_EXT_COUNTER_SELECT_F, &val);
+ perf_count_ext.counterselect = val;
+ mad_decode_field(pc, IB_PC_EXT_XMT_BYTES_F, &val64);
+ aggregate_64bit(&perf_count_ext.portxmitdata, val64);
+ mad_decode_field(pc, IB_PC_EXT_RCV_BYTES_F, &val64);
+ aggregate_64bit(&perf_count_ext.portrcvdata, val64);
+ mad_decode_field(pc, IB_PC_EXT_XMT_PKTS_F, &val64);
+ aggregate_64bit(&perf_count_ext.portxmitpkts, val64);
+ mad_decode_field(pc, IB_PC_EXT_RCV_PKTS_F, &val64);
+ aggregate_64bit(&perf_count_ext.portrcvpkts, val64);
+
+ if (cap_mask & IB_PM_EXT_WIDTH_SUPPORTED) {
+ mad_decode_field(pc, IB_PC_EXT_XMT_UPKTS_F, &val64);
+ aggregate_64bit(&perf_count_ext.portunicastxmitpkts, val64);
+ mad_decode_field(pc, IB_PC_EXT_RCV_UPKTS_F, &val64);
+ aggregate_64bit(&perf_count_ext.portunicastrcvpkts, val64);
+ mad_decode_field(pc, IB_PC_EXT_XMT_MPKTS_F, &val64);
+ aggregate_64bit(&perf_count_ext.portmulticastxmitpkits, val64);
+ mad_decode_field(pc, IB_PC_EXT_RCV_MPKTS_F, &val64);
+ aggregate_64bit(&perf_count_ext.portmulticastrcvpkts, val64);
+ }
+
+ if (htonl(cap_mask2) & IB_PM_IS_ADDL_PORT_CTRS_EXT_SUP) {
+ mad_decode_field(pc, IB_PC_EXT_COUNTER_SELECT2_F, &val);
+ perf_count_ext.counterSelect2 = val;
+ mad_decode_field(pc, IB_PC_EXT_ERR_SYM_F, &val64);
+ aggregate_64bit(&perf_count_ext.symbolErrorCounter, val64);
+ mad_decode_field(pc, IB_PC_EXT_LINK_RECOVERS_F, &val64);
+ aggregate_64bit(&perf_count_ext.linkErrorRecoveryCounter, val64);
+ mad_decode_field(pc, IB_PC_EXT_LINK_DOWNED_F, &val64);
+ aggregate_64bit(&perf_count_ext.linkDownedCounter, val64);
+ mad_decode_field(pc, IB_PC_EXT_ERR_RCV_F, &val64);
+ aggregate_64bit(&perf_count_ext.portRcvErrors, val64);
+ mad_decode_field(pc, IB_PC_EXT_ERR_PHYSRCV_F, &val64);
+ aggregate_64bit(&perf_count_ext.portRcvRemotePhysicalErrors, val64);
+ mad_decode_field(pc, IB_PC_EXT_ERR_SWITCH_REL_F, &val64);
+ aggregate_64bit(&perf_count_ext.portRcvSwitchRelayErrors, val64);
+ mad_decode_field(pc, IB_PC_EXT_XMT_DISCARDS_F, &val64);
+ aggregate_64bit(&perf_count_ext.portXmitDiscards, val64);
+ mad_decode_field(pc, IB_PC_EXT_ERR_XMTCONSTR_F, &val64);
+ aggregate_64bit(&perf_count_ext.portXmitConstraintErrors, val64);
+ mad_decode_field(pc, IB_PC_EXT_ERR_RCVCONSTR_F, &val64);
+ aggregate_64bit(&perf_count_ext.portRcvConstraintErrors, val64);
+ mad_decode_field(pc, IB_PC_EXT_ERR_LOCALINTEG_F, &val64);
+ aggregate_64bit(&perf_count_ext.localLinkIntegrityErrors, val64);
+ mad_decode_field(pc, IB_PC_EXT_ERR_EXCESS_OVR_F, &val64);
+ aggregate_64bit(&perf_count_ext.excessiveBufferOverrunErrors, val64);
+ mad_decode_field(pc, IB_PC_EXT_VL15_DROPPED_F, &val64);
+ aggregate_64bit(&perf_count_ext.VL15Dropped, val64);
+ mad_decode_field(pc, IB_PC_EXT_XMT_WAIT_F, &val64);
+ aggregate_64bit(&perf_count_ext.portXmitWait, val64);
+ mad_decode_field(pc, IB_PC_EXT_QP1_DROP_F, &val64);
+ aggregate_64bit(&perf_count_ext.QP1Dropped, val64);
+ }
+}
+
+static void output_aggregate_perfcounters_ext(ib_portid_t * portid,
+ uint16_t cap_mask, uint32_t cap_mask2)
+{
+ char buf[1536];
+ uint32_t val = ALL_PORTS;
+
+ memset(buf, 0, sizeof(buf));
+
+ /* set port_select to 255 to emulate AllPortSelect */
+ mad_encode_field(pc, IB_PC_EXT_PORT_SELECT_F, &val);
+ mad_encode_field(pc, IB_PC_EXT_COUNTER_SELECT_F,
+ &perf_count_ext.counterselect);
+ mad_encode_field(pc, IB_PC_EXT_XMT_BYTES_F,
+ &perf_count_ext.portxmitdata);
+ mad_encode_field(pc, IB_PC_EXT_RCV_BYTES_F,
+ &perf_count_ext.portrcvdata);
+ mad_encode_field(pc, IB_PC_EXT_XMT_PKTS_F,
+ &perf_count_ext.portxmitpkts);
+ mad_encode_field(pc, IB_PC_EXT_RCV_PKTS_F, &perf_count_ext.portrcvpkts);
+
+ if (cap_mask & IB_PM_EXT_WIDTH_SUPPORTED) {
+ mad_encode_field(pc, IB_PC_EXT_XMT_UPKTS_F,
+ &perf_count_ext.portunicastxmitpkts);
+ mad_encode_field(pc, IB_PC_EXT_RCV_UPKTS_F,
+ &perf_count_ext.portunicastrcvpkts);
+ mad_encode_field(pc, IB_PC_EXT_XMT_MPKTS_F,
+ &perf_count_ext.portmulticastxmitpkits);
+ mad_encode_field(pc, IB_PC_EXT_RCV_MPKTS_F,
+ &perf_count_ext.portmulticastrcvpkts);
+ }
+
+ if (htonl(cap_mask2) & IB_PM_IS_ADDL_PORT_CTRS_EXT_SUP) {
+ mad_encode_field(pc, IB_PC_EXT_COUNTER_SELECT2_F,
+ &perf_count_ext.counterSelect2);
+ mad_encode_field(pc, IB_PC_EXT_ERR_SYM_F,
+ &perf_count_ext.symbolErrorCounter);
+ mad_encode_field(pc, IB_PC_EXT_LINK_RECOVERS_F,
+ &perf_count_ext.linkErrorRecoveryCounter);
+ mad_encode_field(pc, IB_PC_EXT_LINK_DOWNED_F,
+ &perf_count_ext.linkDownedCounter);
+ mad_encode_field(pc, IB_PC_EXT_ERR_RCV_F,
+ &perf_count_ext.portRcvErrors);
+ mad_encode_field(pc, IB_PC_EXT_ERR_PHYSRCV_F,
+ &perf_count_ext.portRcvRemotePhysicalErrors);
+ mad_encode_field(pc, IB_PC_EXT_ERR_SWITCH_REL_F,
+ &perf_count_ext.portRcvSwitchRelayErrors);
+ mad_encode_field(pc, IB_PC_EXT_XMT_DISCARDS_F,
+ &perf_count_ext.portXmitDiscards);
+ mad_encode_field(pc, IB_PC_EXT_ERR_XMTCONSTR_F,
+ &perf_count_ext.portXmitConstraintErrors);
+ mad_encode_field(pc, IB_PC_EXT_ERR_RCVCONSTR_F,
+ &perf_count_ext.portRcvConstraintErrors);
+ mad_encode_field(pc, IB_PC_EXT_ERR_LOCALINTEG_F,
+ &perf_count_ext.localLinkIntegrityErrors);
+ mad_encode_field(pc, IB_PC_EXT_ERR_EXCESS_OVR_F,
+ &perf_count_ext.excessiveBufferOverrunErrors);
+ mad_encode_field(pc, IB_PC_EXT_VL15_DROPPED_F,
+ &perf_count_ext.VL15Dropped);
+ mad_encode_field(pc, IB_PC_EXT_XMT_WAIT_F,
+ &perf_count_ext.portXmitWait);
+ mad_encode_field(pc, IB_PC_EXT_QP1_DROP_F,
+ &perf_count_ext.QP1Dropped);
+ }
+
+ mad_dump_perfcounters_ext(buf, sizeof buf, pc, sizeof pc);
+
+ printf("# Port extended counters: %s port %d (CapMask: 0x%02X CapMask2: 0x%07X)\n%s",
+ portid2str(portid), ALL_PORTS, ntohs(cap_mask), cap_mask2, buf);
+}
+
+static void dump_perfcounters(int extended, int timeout, uint16_t cap_mask,
+ uint32_t cap_mask2, ib_portid_t * portid,
+ int port, int aggregate)
+{
+ char buf[1536];
+
+ if (extended != 1) {
+ memset(pc, 0, sizeof(pc));
+ if (!pma_query_via(pc, portid, port, timeout,
+ IB_GSI_PORT_COUNTERS, srcport))
+ IBEXIT("perfquery");
+ if (!(cap_mask & IB_PM_PC_XMIT_WAIT_SUP)) {
+ /* if PortCounters:PortXmitWait not supported clear this counter */
+ VERBOSE("PortXmitWait not indicated"
+ " so ignore this counter");
+ perf_count.xmtwait = 0;
+ mad_encode_field(pc, IB_PC_XMT_WAIT_F,
+ &perf_count.xmtwait);
+ }
+ if (aggregate)
+ aggregate_perfcounters();
+ else {
+#ifdef HAVE_IB_PC_QP1_DROP_F
+ mad_dump_perfcounters(buf, sizeof buf, pc, sizeof pc);
+#else
+ mad_dump_fields(buf, sizeof buf, pc, sizeof pc,
+ IB_PC_FIRST_F,
+ (cap_mask & IB_PM_PC_XMIT_WAIT_SUP)?IB_PC_LAST_F:(IB_PC_RCV_PKTS_F+1));
+#endif
+ }
+ } else {
+ /* 1.2 errata: bit 9 is extended counter support
+ * bit 10 is extended counter NoIETF
+ */
+ if (!(cap_mask & IB_PM_EXT_WIDTH_SUPPORTED) &&
+ !(cap_mask & IB_PM_EXT_WIDTH_NOIETF_SUP))
+ IBWARN
+ ("PerfMgt ClassPortInfo CapMask 0x%02X; No extended counter support indicated\n",
+ ntohs(cap_mask));
+
+ memset(pc, 0, sizeof(pc));
+ if (!pma_query_via(pc, portid, port, timeout,
+ IB_GSI_PORT_COUNTERS_EXT, srcport))
+ IBEXIT("perfextquery");
+ if (aggregate)
+ aggregate_perfcounters_ext(cap_mask, cap_mask2);
+ else
+ mad_dump_perfcounters_ext(buf, sizeof buf, pc,
+ sizeof pc);
+ }
+
+ if (!aggregate) {
+ if (extended)
+ printf("# Port extended counters: %s port %d "
+ "(CapMask: 0x%02X CapMask2: 0x%07X)\n%s",
+ portid2str(portid), port, ntohs(cap_mask),
+ cap_mask2, buf);
+ else
+ printf("# Port counters: %s port %d "
+ "(CapMask: 0x%02X)\n%s",
+ portid2str(portid), port, ntohs(cap_mask), buf);
+ }
+}
+
+static void reset_counters(int extended, int timeout, int mask,
+ ib_portid_t * portid, int port)
+{
+ memset(pc, 0, sizeof(pc));
+ if (extended != 1) {
+ if (!performance_reset_via(pc, portid, port, mask, timeout,
+ IB_GSI_PORT_COUNTERS, srcport))
+ IBEXIT("perf reset");
+ } else {
+ if (!performance_reset_via(pc, portid, port, mask, timeout,
+ IB_GSI_PORT_COUNTERS_EXT, srcport))
+ IBEXIT("perf ext reset");
+ }
+}
+
+static int reset, reset_only, all_ports, loop_ports, port, extended, xmt_sl,
+ rcv_sl, xmt_disc, rcv_err, extended_speeds, smpl_ctl, oprcvcounters, flowctlcounters,
+ vloppackets, vlopdata, vlxmitflowctlerrors, vlxmitcounters, swportvlcong,
+ rcvcc, slrcvfecn, slrcvbecn, xmitcc, vlxmittimecc;
+static int ports[MAX_PORTS];
+static int ports_count;
+
+static void common_func(ib_portid_t * portid, int port_num, int mask,
+ unsigned query, unsigned reset,
+ const char *name, uint16_t attr,
+ void dump_func(char *, int, void *, int))
+{
+ char buf[1536];
+
+ if (query) {
+ memset(pc, 0, sizeof(pc));
+ if (!pma_query_via(pc, portid, port_num, ibd_timeout, attr,
+ srcport))
+ IBEXIT("cannot query %s", name);
+
+ dump_func(buf, sizeof(buf), pc, sizeof(pc));
+
+ printf("# %s counters: %s port %d\n%s", name,
+ portid2str(portid), port_num, buf);
+ }
+
+ memset(pc, 0, sizeof(pc));
+ if (reset && !performance_reset_via(pc, portid, port, mask, ibd_timeout,
+ attr, srcport))
+ IBEXIT("cannot reset %s", name);
+}
+
+static void xmt_sl_query(ib_portid_t * portid, int port, int mask)
+{
+ common_func(portid, port, mask, !reset_only, (reset_only || reset),
+ "PortXmitDataSL", IB_GSI_PORT_XMIT_DATA_SL,
+ mad_dump_perfcounters_xmt_sl);
+}
+
+static void rcv_sl_query(ib_portid_t * portid, int port, int mask)
+{
+ common_func(portid, port, mask, !reset_only, (reset_only || reset),
+ "PortRcvDataSL", IB_GSI_PORT_RCV_DATA_SL,
+ mad_dump_perfcounters_rcv_sl);
+}
+
+static void xmt_disc_query(ib_portid_t * portid, int port, int mask)
+{
+ common_func(portid, port, mask, !reset_only, (reset_only || reset),
+ "PortXmitDiscardDetails", IB_GSI_PORT_XMIT_DISCARD_DETAILS,
+ mad_dump_perfcounters_xmt_disc);
+}
+
+static void rcv_err_query(ib_portid_t * portid, int port, int mask)
+{
+ common_func(portid, port, mask, !reset_only, (reset_only || reset),
+ "PortRcvErrorDetails", IB_GSI_PORT_RCV_ERROR_DETAILS,
+ mad_dump_perfcounters_rcv_err);
+}
+
+static uint8_t *ext_speeds_reset_via(void *rcvbuf, ib_portid_t * dest,
+ int port, uint64_t mask, unsigned timeout,
+ const struct ibmad_port * srcport)
+{
+ ib_rpc_t rpc = { 0 };
+ int lid = dest->lid;
+
+ DEBUG("lid %u port %d mask 0x%" PRIx64, lid, port, mask);
+
+ if (lid == -1) {
+ IBWARN("only lid routed is supported");
+ return NULL;
+ }
+
+ if (!mask)
+ mask = ~0;
+
+ rpc.mgtclass = IB_PERFORMANCE_CLASS;
+ rpc.method = IB_MAD_METHOD_SET;
+ rpc.attr.id = IB_GSI_PORT_EXT_SPEEDS_COUNTERS;
+
+ memset(rcvbuf, 0, IB_MAD_SIZE);
+
+ mad_set_field(rcvbuf, 0, IB_PESC_PORT_SELECT_F, port);
+ mad_set_field64(rcvbuf, 0, IB_PESC_COUNTER_SELECT_F, mask);
+ rpc.attr.mod = 0;
+ rpc.timeout = timeout;
+ rpc.datasz = IB_PC_DATA_SZ;
+ rpc.dataoffs = IB_PC_DATA_OFFS;
+ if (!dest->qp)
+ dest->qp = 1;
+ if (!dest->qkey)
+ dest->qkey = IB_DEFAULT_QP1_QKEY;
+
+ return mad_rpc(srcport, &rpc, dest, rcvbuf, rcvbuf);
+}
+
+static uint8_t is_rsfec_mode_active(ib_portid_t * portid, int port,
+ uint16_t cap_mask)
+{
+ uint8_t data[IB_SMP_DATA_SIZE] = { 0 };
+ uint32_t fec_mode_active = 0;
+ uint32_t pie_capmask = 0;
+ if (cap_mask & IS_PM_RSFEC_COUNTERS_SUP) {
+ if (!is_port_info_extended_supported(portid, port, srcport)) {
+ IBWARN("Port Info Extended not supported");
+ return 0;
+ }
+
+ if (!smp_query_via(data, portid, IB_ATTR_PORT_INFO_EXT, port, 0,
+ srcport))
+ IBEXIT("smp query portinfo extended failed");
+
+ mad_decode_field(data, IB_PORT_EXT_CAPMASK_F, &pie_capmask);
+ mad_decode_field(data, IB_PORT_EXT_FEC_MODE_ACTIVE_F,
+ &fec_mode_active);
+ if((pie_capmask &
+ CL_NTOH32(IB_PORT_EXT_CAP_IS_FEC_MODE_SUPPORTED)) &&
+ (CL_NTOH16(IB_PORT_EXT_RS_FEC_MODE_ACTIVE) == (fec_mode_active & 0xffff)))
+ return 1;
+ }
+
+ return 0;
+}
+
+static void extended_speeds_query(ib_portid_t * portid, int port,
+ uint64_t ext_mask, uint16_t cap_mask)
+{
+ int mask = ext_mask;
+
+ if (!reset_only) {
+ if (is_rsfec_mode_active(portid, port, cap_mask))
+ common_func(portid, port, mask, 1, 0,
+ "PortExtendedSpeedsCounters with RS-FEC Active",
+ IB_GSI_PORT_EXT_SPEEDS_COUNTERS,
+ mad_dump_port_ext_speeds_counters_rsfec_active);
+ else
+ common_func(portid, port, mask, 1, 0,
+ "PortExtendedSpeedsCounters",
+ IB_GSI_PORT_EXT_SPEEDS_COUNTERS,
+ mad_dump_port_ext_speeds_counters);
+ }
+
+ if ((reset_only || reset) &&
+ !ext_speeds_reset_via(pc, portid, port, ext_mask, ibd_timeout, srcport))
+ IBEXIT("cannot reset PortExtendedSpeedsCounters");
+}
+
+static void oprcvcounters_query(ib_portid_t * portid, int port, int mask)
+{
+ common_func(portid, port, mask, !reset_only, (reset_only || reset),
+ "PortOpRcvCounters", IB_GSI_PORT_PORT_OP_RCV_COUNTERS,
+ mad_dump_perfcounters_port_op_rcv_counters);
+}
+
+static void flowctlcounters_query(ib_portid_t * portid, int port, int mask)
+{
+ common_func(portid, port, mask, !reset_only, (reset_only || reset),
+ "PortFlowCtlCounters", IB_GSI_PORT_PORT_FLOW_CTL_COUNTERS,
+ mad_dump_perfcounters_port_flow_ctl_counters);
+}
+
+static void vloppackets_query(ib_portid_t * portid, int port, int mask)
+{
+ common_func(portid, port, mask, !reset_only, (reset_only || reset),
+ "PortVLOpPackets", IB_GSI_PORT_PORT_VL_OP_PACKETS,
+ mad_dump_perfcounters_port_vl_op_packet);
+}
+
+static void vlopdata_query(ib_portid_t * portid, int port, int mask)
+{
+ common_func(portid, port, mask, !reset_only, (reset_only || reset),
+ "PortVLOpData", IB_GSI_PORT_PORT_VL_OP_DATA,
+ mad_dump_perfcounters_port_vl_op_data);
+}
+
+static void vlxmitflowctlerrors_query(ib_portid_t * portid, int port, int mask)
+{
+ common_func(portid, port, mask, !reset_only, (reset_only || reset),
+ "PortVLXmitFlowCtlUpdateErrors", IB_GSI_PORT_PORT_VL_XMIT_FLOW_CTL_UPDATE_ERRORS,
+ mad_dump_perfcounters_port_vl_xmit_flow_ctl_update_errors);
+}
+
+static void vlxmitcounters_query(ib_portid_t * portid, int port, int mask)
+{
+ common_func(portid, port, mask, !reset_only, (reset_only || reset),
+ "PortVLXmitWaitCounters", IB_GSI_PORT_PORT_VL_XMIT_WAIT_COUNTERS,
+ mad_dump_perfcounters_port_vl_xmit_wait_counters);
+}
+
+static void swportvlcong_query(ib_portid_t * portid, int port, int mask)
+{
+ common_func(portid, port, mask, !reset_only, (reset_only || reset),
+ "SwPortVLCongestion", IB_GSI_SW_PORT_VL_CONGESTION,
+ mad_dump_perfcounters_sw_port_vl_congestion);
+}
+
+static void rcvcc_query(ib_portid_t * portid, int port, int mask)
+{
+ common_func(portid, port, mask, !reset_only, (reset_only || reset),
+ "PortRcvConCtrl", IB_GSI_PORT_RCV_CON_CTRL,
+ mad_dump_perfcounters_rcv_con_ctrl);
+}
+
+static void slrcvfecn_query(ib_portid_t * portid, int port, int mask)
+{
+ common_func(portid, port, mask, !reset_only, (reset_only || reset),
+ "PortSLRcvFECN", IB_GSI_PORT_SL_RCV_FECN,
+ mad_dump_perfcounters_sl_rcv_fecn);
+}
+
+static void slrcvbecn_query(ib_portid_t * portid, int port, int mask)
+{
+ common_func(portid, port, mask, !reset_only, (reset_only || reset),
+ "PortSLRcvBECN", IB_GSI_PORT_SL_RCV_BECN,
+ mad_dump_perfcounters_sl_rcv_becn);
+}
+
+static void xmitcc_query(ib_portid_t * portid, int port, int mask)
+{
+ common_func(portid, port, mask, !reset_only, (reset_only || reset),
+ "PortXmitConCtrl", IB_GSI_PORT_XMIT_CON_CTRL,
+ mad_dump_perfcounters_xmit_con_ctrl);
+}
+
+static void vlxmittimecc_query(ib_portid_t * portid, int port, int mask)
+{
+ common_func(portid, port, mask, !reset_only, (reset_only || reset),
+ "PortVLXmitTimeCong", IB_GSI_PORT_VL_XMIT_TIME_CONG,
+ mad_dump_perfcounters_vl_xmit_time_cong);
+}
+
+void dump_portsamples_control(ib_portid_t * portid, int port)
+{
+ char buf[1280];
+
+ memset(pc, 0, sizeof(pc));
+ if (!pma_query_via(pc, portid, port, ibd_timeout,
+ IB_GSI_PORT_SAMPLES_CONTROL, srcport))
+ IBEXIT("sampctlquery");
+
+ mad_dump_portsamples_control(buf, sizeof buf, pc, sizeof pc);
+ printf("# PortSamplesControl: %s port %d\n%s", portid2str(portid),
+ port, buf);
+}
+
+static int process_opt(void *context, int ch, char *optarg)
+{
+ switch (ch) {
+ case 'x':
+ extended = 1;
+ break;
+ case 'X':
+ xmt_sl = 1;
+ break;
+ case 'S':
+ rcv_sl = 1;
+ break;
+ case 'D':
+ xmt_disc = 1;
+ break;
+ case 'E':
+ rcv_err = 1;
+ break;
+ case 'T':
+ extended_speeds = 1;
+ break;
+ case 'c':
+ smpl_ctl = 1;
+ break;
+ case 1:
+ oprcvcounters = 1;
+ break;
+ case 2:
+ flowctlcounters = 1;
+ break;
+ case 3:
+ vloppackets = 1;
+ break;
+ case 4:
+ vlopdata = 1;
+ break;
+ case 5:
+ vlxmitflowctlerrors = 1;
+ break;
+ case 6:
+ vlxmitcounters = 1;
+ break;
+ case 7:
+ swportvlcong = 1;
+ break;
+ case 8:
+ rcvcc = 1;
+ break;
+ case 9:
+ slrcvfecn = 1;
+ break;
+ case 10:
+ slrcvbecn = 1;
+ break;
+ case 11:
+ xmitcc = 1;
+ break;
+ case 12:
+ vlxmittimecc = 1;
+ break;
+ case 'a':
+ all_ports++;
+ port = ALL_PORTS;
+ break;
+ case 'l':
+ loop_ports++;
+ break;
+ case 'r':
+ reset++;
+ break;
+ case 'R':
+ reset_only++;
+ break;
+ case 25:
+ if (!inet_pton(AF_INET6, optarg, &dgid)) {
+ fprintf(stderr, "dgid format is wrong!\n");
+ ibdiag_show_usage();
+ return 1;
+ }
+ with_grh = 1;
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ int mgmt_classes[3] = { IB_SMI_CLASS, IB_SA_CLASS, IB_PERFORMANCE_CLASS };
+ ib_portid_t portid = { 0 };
+ int mask = 0xffff;
+ uint64_t ext_mask = 0xffffffffffffffffULL;
+ uint32_t cap_mask2;
+ uint16_t cap_mask;
+ int all_ports_loop = 0;
+ int node_type, num_ports = 0;
+ uint8_t data[IB_SMP_DATA_SIZE] = { 0 };
+ int start_port = 1;
+ int enhancedport0;
+ char *tmpstr;
+ int i;
+
+ const struct ibdiag_opt opts[] = {
+ {"extended", 'x', 0, NULL, "show extended port counters"},
+ {"xmtsl", 'X', 0, NULL, "show Xmt SL port counters"},
+ {"rcvsl", 'S', 0, NULL, "show Rcv SL port counters"},
+ {"xmtdisc", 'D', 0, NULL, "show Xmt Discard Details"},
+ {"rcverr", 'E', 0, NULL, "show Rcv Error Details"},
+ {"extended_speeds", 'T', 0, NULL, "show port extended speeds counters"},
+ {"oprcvcounters", 1, 0, NULL, "show Rcv Counters per Op code"},
+ {"flowctlcounters", 2, 0, NULL, "show flow control counters"},
+ {"vloppackets", 3, 0, NULL, "show packets received per Op code per VL"},
+ {"vlopdata", 4, 0, NULL, "show data received per Op code per VL"},
+ {"vlxmitflowctlerrors", 5, 0, NULL, "show flow control update errors per VL"},
+ {"vlxmitcounters", 6, 0, NULL, "show ticks waiting to transmit counters per VL"},
+ {"swportvlcong", 7, 0, NULL, "show sw port VL congestion"},
+ {"rcvcc", 8, 0, NULL, "show Rcv congestion control counters"},
+ {"slrcvfecn", 9, 0, NULL, "show SL Rcv FECN counters"},
+ {"slrcvbecn", 10, 0, NULL, "show SL Rcv BECN counters"},
+ {"xmitcc", 11, 0, NULL, "show Xmit congestion control counters"},
+ {"vlxmittimecc", 12, 0, NULL, "show VL Xmit Time congestion control counters"},
+ {"smplctl", 'c', 0, NULL, "show samples control"},
+ {"all_ports", 'a', 0, NULL, "show aggregated counters"},
+ {"loop_ports", 'l', 0, NULL, "iterate through each port"},
+ {"reset_after_read", 'r', 0, NULL, "reset counters after read"},
+ {"Reset_only", 'R', 0, NULL, "only reset counters"},
+ {"dgid", 25, 1, NULL, "remote gid (IPv6 format)"},
+ {0}
+ };
+ char usage_args[] = " [<lid|guid> [[port(s)] [reset_mask]]]";
+ const char *usage_examples[] = {
+ "\t\t# read local port's performance counters",
+ "32 1\t\t# read performance counters from lid 32, port 1",
+ "-x 32 1\t# read extended performance counters from lid 32, port 1",
+ "-a 32\t\t# read performance counters from lid 32, all ports",
+ "-r 32 1\t# read performance counters and reset",
+ "-x -r 32 1\t# read extended performance counters and reset",
+ "-R 0x20 1\t# reset performance counters of port 1 only",
+ "-x -R 0x20 1\t# reset extended performance counters of port 1 only",
+ "-R -a 32\t# reset performance counters of all ports",
+ "-R 32 2 0x0fff\t# reset only error counters of port 2",
+ "-R 32 2 0xf000\t# reset only non-error counters of port 2",
+ "-a 32 1-10\t# read performance counters from lid 32, port 1-10, aggregate output",
+ "-l 32 1-10\t# read performance counters from lid 32, port 1-10, output each port",
+ "-a 32 1,4,8\t# read performance counters from lid 32, port 1, 4, and 8, aggregate output",
+ "-l 32 1,4,8\t# read performance counters from lid 32, port 1, 4, and 8, output each port",
+ NULL,
+ };
+
+ ibdiag_process_opts(argc, argv, NULL, "DK", opts, process_opt,
+ usage_args, usage_examples);
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc > 1) {
+ if (strchr(argv[1], ',')) {
+ tmpstr = strtok(argv[1], ",");
+ while (tmpstr) {
+ ports[ports_count++] = strtoul(tmpstr, 0, 0);
+ tmpstr = strtok(NULL, ",");
+ }
+ port = ports[0];
+ }
+ else if ((tmpstr = strchr(argv[1], '-'))) {
+ int pmin, pmax;
+
+ *tmpstr = '\0';
+ tmpstr++;
+
+ pmin = strtoul(argv[1], 0, 0);
+ pmax = strtoul(tmpstr, 0, 0);
+
+ if (pmin >= pmax)
+ IBEXIT("max port must be greater than min port in range");
+
+ while (pmin <= pmax)
+ ports[ports_count++] = pmin++;
+
+ port = ports[0];
+ }
+ else
+ port = strtoul(argv[1], 0, 0);
+ }
+ if (argc > 2) {
+ ext_mask = strtoull(argv[2], 0, 0);
+ mask = ext_mask;
+ }
+
+ srcport = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 3);
+ if (!srcport)
+ IBEXIT("Failed to open '%s' port '%d'", ibd_ca, ibd_ca_port);
+
+ smp_mkey_set(srcport, ibd_mkey);
+
+ if (argc) {
+ if (with_grh && ibd_dest_type != IB_DEST_LID)
+ IBEXIT("When using GRH, LID should be provided");
+ if (resolve_portid_str(ibd_ca, ibd_ca_port, &portid, argv[0],
+ ibd_dest_type, ibd_sm_id, srcport) < 0)
+ IBEXIT("can't resolve destination port %s", argv[0]);
+ if (with_grh) {
+ portid.grh_present = 1;
+ memcpy(&portid.gid, &dgid, sizeof(portid.gid));
+ }
+ } else {
+ if (resolve_self(ibd_ca, ibd_ca_port, &portid, &port, 0) < 0)
+ IBEXIT("can't resolve self port %s", argv[0]);
+ }
+
+ /* PerfMgt ClassPortInfo is a required attribute */
+ memset(pc, 0, sizeof(pc));
+ if (!pma_query_via(pc, &portid, port, ibd_timeout, CLASS_PORT_INFO,
+ srcport))
+ IBEXIT("classportinfo query");
+ /* ClassPortInfo should be supported as part of libibmad */
+ memcpy(&cap_mask, pc + 2, sizeof(cap_mask)); /* CapabilityMask */
+ memcpy(&cap_mask2, pc + 4, sizeof(cap_mask2)); /* CapabilityMask2 */
+ cap_mask2 = ntohl(cap_mask2) >> 5;
+
+ if (!(cap_mask & IB_PM_ALL_PORT_SELECT)) { /* bit 8 is AllPortSelect */
+ if (!all_ports && port == ALL_PORTS)
+ IBEXIT("AllPortSelect not supported");
+ if (all_ports && port == ALL_PORTS)
+ all_ports_loop = 1;
+ }
+
+ if (xmt_sl) {
+ xmt_sl_query(&portid, port, mask);
+ goto done;
+ }
+
+ if (rcv_sl) {
+ rcv_sl_query(&portid, port, mask);
+ goto done;
+ }
+
+ if (xmt_disc) {
+ xmt_disc_query(&portid, port, mask);
+ goto done;
+ }
+
+ if (rcv_err) {
+ rcv_err_query(&portid, port, mask);
+ goto done;
+ }
+
+ if (extended_speeds) {
+ extended_speeds_query(&portid, port, ext_mask, cap_mask);
+ goto done;
+ }
+
+ if (oprcvcounters) {
+ oprcvcounters_query(&portid, port, mask);
+ goto done;
+ }
+
+ if (flowctlcounters) {
+ flowctlcounters_query(&portid, port, mask);
+ goto done;
+ }
+
+ if (vloppackets) {
+ vloppackets_query(&portid, port, mask);
+ goto done;
+ }
+
+ if (vlopdata) {
+ vlopdata_query(&portid, port, mask);
+ goto done;
+ }
+
+ if (vlxmitflowctlerrors) {
+ vlxmitflowctlerrors_query(&portid, port, mask);
+ goto done;
+ }
+
+ if (vlxmitcounters) {
+ vlxmitcounters_query(&portid, port, mask);
+ goto done;
+ }
+
+ if (swportvlcong) {
+ swportvlcong_query(&portid, port, mask);
+ goto done;
+ }
+
+ if (rcvcc) {
+ rcvcc_query(&portid, port, mask);
+ goto done;
+ }
+
+ if (slrcvfecn) {
+ slrcvfecn_query(&portid, port, mask);
+ goto done;
+ }
+
+ if (slrcvbecn) {
+ slrcvbecn_query(&portid, port, mask);
+ goto done;
+ }
+
+ if (xmitcc) {
+ xmitcc_query(&portid, port, mask);
+ goto done;
+ }
+
+ if (vlxmittimecc) {
+ vlxmittimecc_query(&portid, port, mask);
+ goto done;
+ }
+
+ if (smpl_ctl) {
+ dump_portsamples_control(&portid, port);
+ goto done;
+ }
+
+
+ if (all_ports_loop || (loop_ports && (all_ports || port == ALL_PORTS))) {
+ if (!smp_query_via(data, &portid, IB_ATTR_NODE_INFO, 0, 0,
+ srcport))
+ IBEXIT("smp query nodeinfo failed");
+ node_type = mad_get_field(data, 0, IB_NODE_TYPE_F);
+ mad_decode_field(data, IB_NODE_NPORTS_F, &num_ports);
+ if (!num_ports)
+ IBEXIT("smp query nodeinfo: num ports invalid");
+
+ if (node_type == IB_NODE_SWITCH) {
+ if (!smp_query_via(data, &portid, IB_ATTR_SWITCH_INFO,
+ 0, 0, srcport))
+ IBEXIT("smp query nodeinfo failed");
+ enhancedport0 =
+ mad_get_field(data, 0, IB_SW_ENHANCED_PORT0_F);
+ if (enhancedport0)
+ start_port = 0;
+ }
+ if (all_ports_loop && !loop_ports)
+ IBWARN
+ ("Emulating AllPortSelect by iterating through all ports");
+ }
+
+ if (reset_only)
+ goto do_reset;
+
+ if (all_ports_loop || (loop_ports && (all_ports || port == ALL_PORTS))) {
+ for (i = start_port; i <= num_ports; i++)
+ dump_perfcounters(extended, ibd_timeout,
+ cap_mask, cap_mask2,
+ &portid, i, (all_ports_loop
+ && !loop_ports));
+ if (all_ports_loop && !loop_ports) {
+ if (extended != 1)
+ output_aggregate_perfcounters(&portid,
+ cap_mask);
+ else
+ output_aggregate_perfcounters_ext(&portid,
+ cap_mask, cap_mask2);
+ }
+ } else if (ports_count > 1) {
+ for (i = 0; i < ports_count; i++)
+ dump_perfcounters(extended, ibd_timeout, cap_mask,
+ cap_mask2, &portid, ports[i],
+ (all_ports && !loop_ports));
+ if (all_ports && !loop_ports) {
+ if (extended != 1)
+ output_aggregate_perfcounters(&portid,
+ cap_mask);
+ else
+ output_aggregate_perfcounters_ext(&portid,
+ cap_mask, cap_mask2);
+ }
+ } else
+ dump_perfcounters(extended, ibd_timeout, cap_mask, cap_mask2,
+ &portid, port, 0);
+
+ if (!reset)
+ goto done;
+
+do_reset:
+ if (argc <= 2 && !extended) {
+ if (cap_mask & IB_PM_PC_XMIT_WAIT_SUP)
+ mask |= (1 << 16); /* reset portxmitwait */
+ if (cap_mask & IB_PM_IS_QP1_DROP_SUP)
+ mask |= (1 << 17); /* reset qp1dropped */
+ }
+
+ if (extended) {
+ mask |= 0xfff0000;
+ if (cap_mask & IB_PM_PC_XMIT_WAIT_SUP)
+ mask |= (1 << 28);
+ if (cap_mask & IB_PM_IS_QP1_DROP_SUP)
+ mask |= (1 << 29);
+ }
+
+ if (all_ports_loop || (loop_ports && (all_ports || port == ALL_PORTS))) {
+ for (i = start_port; i <= num_ports; i++)
+ reset_counters(extended, ibd_timeout, mask, &portid, i);
+ } else if (ports_count > 1) {
+ for (i = 0; i < ports_count; i++)
+ reset_counters(extended, ibd_timeout, mask, &portid, ports[i]);
+ } else
+ reset_counters(extended, ibd_timeout, mask, &portid, port);
+
+done:
+ mad_rpc_close_port(srcport);
+ exit(0);
+}
diff --git a/contrib/ofed/infiniband-diags/src/rdma-ndd.c b/contrib/ofed/infiniband-diags/src/rdma-ndd.c
new file mode 100644
index 000000000000..194c2cd86574
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/src/rdma-ndd.c
@@ -0,0 +1,433 @@
+/*
+ * Copyright (c) 2014 Intel Corporation. All Rights Reserved
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <poll.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <string.h>
+#include <limits.h>
+#include <stdio.h>
+#include <syslog.h>
+#include <dirent.h>
+#include <errno.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <stdlib.h>
+
+#include <libudev.h>
+
+struct udev *udev;
+struct udev_monitor *mon;
+
+#include "ibdiag_common.h"
+
+#define SYS_HOSTNAME "/proc/sys/kernel/hostname"
+#define DEF_SYS_DIR "/sys"
+char *sys_dir = DEF_SYS_DIR;
+#define SYS_INFINIBAND "class/infiniband"
+#define DEFAULT_RETRY_RATE 60
+#define DEFAULT_RETRY_COUNT 0
+#define DEFAULT_ND_FORMAT "%h %d"
+
+int failure_retry_rate = DEFAULT_RETRY_RATE;
+int set_retry_cnt = DEFAULT_RETRY_COUNT;
+int foreground = 0;
+char *pidfile = NULL;
+
+static void newline_to_null(char *str)
+{
+ char *term = index(str, '\n');
+ if (term)
+ *term = '\0';
+}
+
+static void strip_domain(char *str)
+{
+ char *term = index(str, '.');
+ if (term)
+ *term = '\0';
+}
+
+static void build_node_desc(char *dest, size_t len,
+ const char *device, const char *hostname)
+{
+ char *end = dest + len-1;
+ const char *field;
+ char *src = ibd_nd_format;
+
+ while (*src && (dest < end)) {
+ if (*src != '%') {
+ *dest++ = *src++;
+ } else {
+ src++;
+ switch (*src) {
+ case 'h':
+ field = hostname;
+ while (*field && (*field != '.') && (dest < end))
+ *dest++ = *field++;
+ break;
+ case 'd':
+ field = device;
+ while (*field && (dest < end))
+ *dest++ = *field++;
+ break;
+ }
+ src++;
+ }
+ }
+ *dest = 0;
+}
+
+static int update_node_desc(const char *device, const char *hostname, int force)
+{
+ int rc;
+ char nd[128];
+ char new_nd[64];
+ char nd_file[PATH_MAX];
+ FILE *f;
+
+ snprintf(nd_file, sizeof(nd_file), "%s/%s/%s/node_desc",
+ sys_dir, SYS_INFINIBAND, device);
+ nd_file[sizeof(nd_file)-1] = '\0';
+
+ f = fopen(nd_file, "r+");
+ if (!f) {
+ syslog(LOG_ERR, "Failed to open %s\n", nd_file);
+ return -EIO;
+ }
+
+ if (!fgets(nd, sizeof(nd), f)) {
+ syslog(LOG_ERR, "Failed to read %s\n", nd_file);
+ rc = -EIO;
+ goto error;
+ }
+ newline_to_null(nd);
+
+ build_node_desc(new_nd, sizeof(new_nd), device, hostname);
+
+ if (!force && strncmp(new_nd, nd, sizeof(new_nd)) == 0) {
+ syslog(LOG_INFO, "%s: no change (%s)\n", device, new_nd);
+ } else {
+ syslog(LOG_INFO, "%s: change (%s) -> (%s)\n",
+ device, nd, new_nd);
+ rewind(f);
+ fprintf(f, new_nd);
+ }
+
+ rc = 0;
+error:
+ fclose(f);
+ return rc;
+}
+
+static int set_rdma_node_desc(const char *hostname, int force)
+{
+ DIR *class_dir;
+ struct dirent *dent;
+ char dev_dir[PATH_MAX];
+
+ snprintf(dev_dir, sizeof(dev_dir), "%s/%s", sys_dir, SYS_INFINIBAND);
+ dev_dir[sizeof(dev_dir)-1] = '\0';
+
+ class_dir = opendir(dev_dir);
+ if (!class_dir) {
+ syslog(LOG_INFO, "Failed to open %s", dev_dir);
+ return -ENOSYS;
+ }
+
+ while ((dent = readdir(class_dir))) {
+ int retry = set_retry_cnt;
+ if (dent->d_name[0] == '.')
+ continue;
+
+ while (update_node_desc(dent->d_name, hostname, force) && retry > 0) {
+ syslog(LOG_ERR, "retrying set Node Description on %s\n",
+ dent->d_name);
+ retry--;
+ }
+ }
+
+ closedir(class_dir);
+ return 0;
+}
+
+static int read_hostname(int fd, char *name, size_t len)
+{
+ int rc;
+ memset(name, 0, len);
+ if (read(fd, name, len-1) >= 0) {
+ newline_to_null(name);
+ strip_domain(name);
+ rc = 0;
+ } else {
+ syslog(LOG_ERR, "Read %s Failed\n", SYS_HOSTNAME);
+ rc = -EIO;
+ }
+ return rc;
+}
+
+static int process_opts(void *context, int ch, char *optarg)
+{
+ unsigned long tmp;
+ switch (ch) {
+ case 0:
+ pidfile = optarg;
+ break;
+ case 'f':
+ foreground = 1;
+ break;
+ case 't':
+ tmp = strtoul(optarg, NULL, 0);
+ if (tmp >= INT_MAX) {
+ syslog(LOG_ERR,
+ "Invalid retry rate specified: %lu s\n",
+ tmp);
+ } else {
+ failure_retry_rate = (int)tmp;
+ }
+ break;
+ case 'r':
+ tmp = strtoul(optarg, NULL, 0);
+ if (tmp >= INT_MAX) {
+ syslog(LOG_ERR,
+ "Invalid retry count specified: %lu\n",
+ tmp);
+ } else {
+ set_retry_cnt = (int)tmp;
+ }
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+#define MSG_MAX 2048
+static void udev_log_fn(struct udev *ud, int priority, const char *file, int line,
+ const char *fn, const char *format, va_list args)
+{
+ int off = 0;
+ char msg[MSG_MAX];
+ off = snprintf(msg, MSG_MAX, "libudev: %s:%d %s",
+ file, line, fn);
+ if (off < MSG_MAX-1)
+ vsnprintf(msg+off, MSG_MAX-off, format, args);
+ syslog(LOG_ERR, msg);
+}
+
+static void setup_udev(void)
+{
+ udev = udev_new();
+ if (!udev) {
+ syslog(LOG_ERR, "udev_new failed\n");
+ return;
+ }
+
+ udev_set_log_fn(udev, udev_log_fn);
+ udev_set_log_priority(udev, LOG_INFO);
+#if HAVE_UDEV_GET_SYS_PATH
+ sys_dir = (char *)udev_get_sys_path(udev);
+#endif
+}
+
+static int get_udev_fd(void)
+{
+ mon = udev_monitor_new_from_netlink(udev, "udev");
+ if (!mon) {
+ syslog(LOG_ERR, "udev monitoring failed\n");
+ return -1;
+ }
+
+ udev_monitor_filter_add_match_subsystem_devtype(mon, "infiniband", NULL);
+ udev_monitor_enable_receiving(mon);
+ return udev_monitor_get_fd(mon);
+}
+
+static void process_udev_event(int ud_fd, const char *hostname)
+{
+ struct udev_device *dev;
+
+ dev = udev_monitor_receive_device(mon);
+ if (dev) {
+ const char *device = udev_device_get_sysname(dev);
+ const char *action = udev_device_get_action(dev);
+
+ syslog(LOG_INFO, "Device event: %s, %s, %s\n",
+ udev_device_get_subsystem(dev),
+ device, action);
+
+ if (device && action
+ && strncmp(action, "add", sizeof("add")) == 0)
+ update_node_desc(device, hostname, 1);
+
+ udev_device_unref(dev);
+ }
+}
+
+static void monitor(void)
+{
+ char hostname[128];
+ int hn_fd;
+ int rc;
+ struct pollfd fds[2];
+ int numfds = 1;
+ int ud_fd;
+
+ ud_fd = get_udev_fd();
+ if (ud_fd >= 0)
+ numfds = 2;
+
+ while (1) {
+ hn_fd = open(SYS_HOSTNAME, O_RDONLY);
+ if (hn_fd < 0) {
+ syslog(LOG_ERR,
+ "Open %s Failed: retry in %d seconds\n",
+ SYS_HOSTNAME, failure_retry_rate);
+ sleep(failure_retry_rate);
+ continue;
+ }
+
+ fds[0].fd = hn_fd;
+ fds[0].events = 0;
+ fds[0].revents = 0;
+
+ fds[1].fd = ud_fd;
+ fds[1].events = POLLIN;
+ fds[1].revents = 0;
+
+ rc = poll(fds, numfds, -1);
+
+ if (rc > 0) {
+ if (read_hostname(hn_fd, hostname, sizeof(hostname)) != 0)
+ hostname[0] = '\0';
+
+ if (fds[0].revents != 0)
+ syslog(LOG_ERR, "Hostname change: %s\n", hostname);
+
+ if (fds[1].revents != 0)
+ process_udev_event(ud_fd, hostname);
+
+ rc = set_rdma_node_desc((const char *)hostname, 0);
+ } else {
+ syslog(LOG_ERR, "Poll %s Failed\n", SYS_HOSTNAME);
+ rc = -EIO;
+ }
+
+ close(hn_fd);
+
+ if (rc)
+ sleep(failure_retry_rate);
+ }
+}
+
+static void remove_pidfile(void)
+{
+ if (pidfile)
+ unlink(pidfile);
+}
+
+static void write_pidfile(void)
+{
+ FILE *f;
+ if (pidfile) {
+ remove_pidfile();
+ f = fopen(pidfile, "w");
+ if (f) {
+ fprintf(f, "%d\n", getpid());
+ fclose(f);
+ } else {
+ syslog(LOG_ERR, "Failed to write pidfile : %s\n",
+ pidfile);
+ exit(errno);
+ }
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ int fd;
+ char hostname[128];
+
+ openlog("rdma-ndd", LOG_PID | LOG_PERROR, LOG_DAEMON);
+
+ const struct ibdiag_opt opts[] = {
+ {"retry_timer", 't', 1, "<retry_timer>",
+ "Length of time to sleep when system errors occur "
+ "when attempting to poll and or read the hostname "
+ "from the system.\n"},
+ {"retry_count", 'r', 1, "<retry_count>",
+ "Number of times to attempt to retry setting "
+ "of the node description on failure\n"},
+ {"foreground", 'f', 0, NULL, "run in the foreground instead of as a daemon\n"},
+ {"pidfile", 0, 1, "<pidfile>", "specify a pid file (daemon mode only)\n"},
+ {0}
+ };
+
+ ibdiag_process_opts(argc, argv, NULL, "CPDLGtsKyevd", opts,
+ process_opts, "", NULL);
+
+ if (!ibd_nd_format)
+ ibd_nd_format = DEFAULT_ND_FORMAT;
+
+ if (!foreground) {
+ closelog();
+ openlog("rdma-ndd", LOG_PID, LOG_DAEMON);
+ if (daemon(0, 0) != 0) {
+ syslog(LOG_ERR, "Failed to daemonize\n");
+ exit(errno);
+ }
+ write_pidfile();
+ }
+
+ setup_udev();
+
+ syslog(LOG_INFO, "Node Descriptor format (%s)\n", ibd_nd_format);
+
+ fd = open(SYS_HOSTNAME, O_RDONLY);
+ if (read_hostname(fd, hostname, sizeof(hostname)) != 0)
+ hostname[0] = '\0';
+ set_rdma_node_desc((const char *)hostname, 1);
+ close(fd);
+
+ monitor();
+
+ remove_pidfile();
+
+ return 0;
+}
diff --git a/contrib/ofed/infiniband-diags/src/saquery.c b/contrib/ofed/infiniband-diags/src/saquery.c
new file mode 100644
index 000000000000..a4cc3c0a2972
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/src/saquery.c
@@ -0,0 +1,1984 @@
+/*
+ * Copyright (c) 2006,2007 The Regents of the University of California.
+ * Copyright (c) 2004-2009 Voltaire, Inc. All rights reserved.
+ * Copyright (c) 2002-2013 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 1996-2013 Intel Corporation. All rights reserved.
+ * Copyright (c) 2009 HNR Consulting. All rights reserved.
+ *
+ * Produced at Lawrence Livermore National Laboratory.
+ * Written by Ira Weiny <weiny2@llnl.gov>.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <arpa/inet.h>
+#include <ctype.h>
+#include <string.h>
+#include <errno.h>
+
+#define _GNU_SOURCE
+#include <getopt.h>
+
+#include <infiniband/umad.h>
+#include <infiniband/mad.h>
+#include <iba/ib_types.h>
+#include <complib/cl_nodenamemap.h>
+
+#include "ibdiag_common.h"
+#include "ibdiag_sa.h"
+
+#ifndef IB_PR_COMPMASK_SERVICEID
+#define IB_PR_COMPMASK_SERVICEID (IB_PR_COMPMASK_SERVICEID_MSB | \
+ IB_PR_COMPMASK_SERVICEID_LSB)
+#endif
+
+#define UMAD_SA_CAP_MASK2_IS_MCAST_TOP_SUP (1 << 3)
+
+struct query_params {
+ uint64_t service_id;
+ ib_gid_t sgid, dgid, gid, mgid;
+ uint16_t slid, dlid, mlid;
+ uint32_t flow_label;
+ int hop_limit;
+ uint8_t tclass;
+ int reversible, numb_path;
+ uint16_t pkey;
+ int qos_class, sl;
+ uint8_t mtu, rate, pkt_life;
+ uint32_t qkey;
+ uint8_t scope;
+ uint8_t join_state;
+ int proxy_join;
+ ib_class_port_info_t cpi;
+ uint8_t with_grh;
+ ibmad_gid_t sa_dgid;
+};
+
+struct query_cmd {
+ const char *name, *alias;
+ uint16_t query_type;
+ const char *usage;
+ int (*handler) (const struct query_cmd * q, struct sa_handle * h,
+ struct query_params * p, int argc, char *argv[]);
+};
+
+static char *node_name_map_file = NULL;
+static nn_map_t *node_name_map = NULL;
+
+/**
+ * Declare some globals because I don't want this to be too complex.
+ */
+#define MAX_PORTS (8)
+#define DEFAULT_SA_TIMEOUT_MS (1000)
+
+enum {
+ ALL,
+ LID_ONLY,
+ UNIQUE_LID_ONLY,
+ GUID_ONLY,
+ ALL_DESC,
+ NAME_OF_LID,
+ NAME_OF_GUID,
+} node_print_desc = ALL;
+
+char *requested_name = NULL;
+uint16_t requested_lid = 0;
+int requested_lid_flag = 0;
+uint64_t requested_guid = 0;
+int requested_guid_flag = 0;
+
+static unsigned valid_gid(ib_gid_t * gid)
+{
+ ib_gid_t zero_gid;
+ memset(&zero_gid, 0, sizeof zero_gid);
+ return memcmp(&zero_gid, gid, sizeof(*gid));
+}
+
+static void print_node_desc(ib_node_record_t * node_record)
+{
+ ib_node_info_t *p_ni = &(node_record->node_info);
+ ib_node_desc_t *p_nd = &(node_record->node_desc);
+ char *name;
+
+ if (p_ni->node_type == IB_NODE_TYPE_CA) {
+ name = remap_node_name(node_name_map,
+ node_record->node_info.node_guid,
+ (char *)p_nd->description);
+ printf("%6d \"%s\"\n", cl_ntoh16(node_record->lid), name);
+ free(name);
+ }
+}
+
+static void dump_node_record(void *data, struct query_params *p)
+{
+ ib_node_record_t *nr = data;
+ ib_node_info_t *ni = &nr->node_info;
+ char *name = remap_node_name(node_name_map,
+ cl_ntoh64(ni->node_guid),
+ (char *)nr->node_desc.description);
+
+ printf("NodeRecord dump:\n"
+ "\t\tlid.....................%u\n"
+ "\t\treserved................0x%X\n"
+ "\t\tbase_version............0x%X\n"
+ "\t\tclass_version...........0x%X\n"
+ "\t\tnode_type...............%s\n"
+ "\t\tnum_ports...............%u\n"
+ "\t\tsys_guid................0x%016" PRIx64 "\n"
+ "\t\tnode_guid...............0x%016" PRIx64 "\n"
+ "\t\tport_guid...............0x%016" PRIx64 "\n"
+ "\t\tpartition_cap...........0x%X\n"
+ "\t\tdevice_id...............0x%X\n"
+ "\t\trevision................0x%X\n"
+ "\t\tport_num................%u\n"
+ "\t\tvendor_id...............0x%X\n"
+ "\t\tNodeDescription.........%s\n",
+ cl_ntoh16(nr->lid), cl_ntoh16(nr->resv),
+ ni->base_version, ni->class_version,
+ ib_get_node_type_str(ni->node_type), ni->num_ports,
+ cl_ntoh64(ni->sys_guid), cl_ntoh64(ni->node_guid),
+ cl_ntoh64(ni->port_guid), cl_ntoh16(ni->partition_cap),
+ cl_ntoh16(ni->device_id), cl_ntoh32(ni->revision),
+ ib_node_info_get_local_port_num(ni),
+ cl_ntoh32(ib_node_info_get_vendor_id(ni)),
+ name);
+
+ free(name);
+}
+
+static void print_node_record(ib_node_record_t * node_record)
+{
+ ib_node_info_t *p_ni = &node_record->node_info;
+ ib_node_desc_t *p_nd = &node_record->node_desc;
+ char *name;
+
+ switch (node_print_desc) {
+ case LID_ONLY:
+ case UNIQUE_LID_ONLY:
+ printf("%u\n", cl_ntoh16(node_record->lid));
+ return;
+ case GUID_ONLY:
+ printf("0x%016" PRIx64 "\n", cl_ntoh64(p_ni->port_guid));
+ return;
+ case NAME_OF_LID:
+ case NAME_OF_GUID:
+ name = remap_node_name(node_name_map,
+ cl_ntoh64(p_ni->node_guid),
+ (char *)p_nd->description);
+ printf("%s\n", name);
+ free(name);
+ return;
+ case ALL:
+ default:
+ break;
+ }
+
+ dump_node_record(node_record, 0);
+}
+
+static void dump_path_record(void *data, struct query_params *p)
+{
+ char gid_str[INET6_ADDRSTRLEN];
+ char gid_str2[INET6_ADDRSTRLEN];
+ ib_path_rec_t *p_pr = data;
+ printf("PathRecord dump:\n"
+ "\t\tservice_id..............0x%016" PRIx64 "\n"
+ "\t\tdgid....................%s\n"
+ "\t\tsgid....................%s\n"
+ "\t\tdlid....................%u\n"
+ "\t\tslid....................%u\n"
+ "\t\thop_flow_raw............0x%X\n"
+ "\t\ttclass..................0x%X\n"
+ "\t\tnum_path_revers.........0x%X\n"
+ "\t\tpkey....................0x%X\n"
+ "\t\tqos_class...............0x%X\n"
+ "\t\tsl......................0x%X\n"
+ "\t\tmtu.....................0x%X\n"
+ "\t\trate....................0x%X\n"
+ "\t\tpkt_life................0x%X\n"
+ "\t\tpreference..............0x%X\n"
+ "\t\tresv2...................0x%02X%02X%02X%02X%02X%02X\n",
+ cl_ntoh64(p_pr->service_id),
+ inet_ntop(AF_INET6, p_pr->dgid.raw, gid_str, sizeof gid_str),
+ inet_ntop(AF_INET6, p_pr->sgid.raw, gid_str2, sizeof gid_str2),
+ cl_ntoh16(p_pr->dlid), cl_ntoh16(p_pr->slid),
+ cl_ntoh32(p_pr->hop_flow_raw), p_pr->tclass, p_pr->num_path,
+ cl_ntoh16(p_pr->pkey), ib_path_rec_qos_class(p_pr),
+ ib_path_rec_sl(p_pr), p_pr->mtu, p_pr->rate, p_pr->pkt_life,
+ p_pr->preference,
+ p_pr->resv2[0], p_pr->resv2[1], p_pr->resv2[2],
+ p_pr->resv2[3], p_pr->resv2[4], p_pr->resv2[5]);
+}
+
+static void dump_class_port_info(ib_class_port_info_t *cpi)
+{
+ char gid_str[INET6_ADDRSTRLEN];
+ char gid_str2[INET6_ADDRSTRLEN];
+
+ printf("SA ClassPortInfo:\n"
+ "\t\tBase version.............%d\n"
+ "\t\tClass version............%d\n"
+ "\t\tCapability mask..........0x%04X\n"
+ "\t\tCapability mask 2........0x%08X\n"
+ "\t\tResponse time value......0x%02X\n"
+ "\t\tRedirect GID.............%s\n"
+ "\t\tRedirect TC/SL/FL........0x%08X\n"
+ "\t\tRedirect LID.............%u\n"
+ "\t\tRedirect PKey............0x%04X\n"
+ "\t\tRedirect QP..............0x%08X\n"
+ "\t\tRedirect QKey............0x%08X\n"
+ "\t\tTrap GID.................%s\n"
+ "\t\tTrap TC/SL/FL............0x%08X\n"
+ "\t\tTrap LID.................%u\n"
+ "\t\tTrap PKey................0x%04X\n"
+ "\t\tTrap HL/QP...............0x%08X\n"
+ "\t\tTrap QKey................0x%08X\n",
+ cpi->base_ver, cpi->class_ver, cl_ntoh16(cpi->cap_mask),
+ ib_class_cap_mask2(cpi), ib_class_resp_time_val(cpi),
+ inet_ntop(AF_INET6, &(cpi->redir_gid), gid_str, sizeof gid_str),
+ cl_ntoh32(cpi->redir_tc_sl_fl), cl_ntoh16(cpi->redir_lid),
+ cl_ntoh16(cpi->redir_pkey), cl_ntoh32(cpi->redir_qp),
+ cl_ntoh32(cpi->redir_qkey),
+ inet_ntop(AF_INET6, &(cpi->trap_gid), gid_str2, sizeof gid_str2),
+ cl_ntoh32(cpi->trap_tc_sl_fl), cl_ntoh16(cpi->trap_lid),
+ cl_ntoh16(cpi->trap_pkey), cl_ntoh32(cpi->trap_hop_qp),
+ cl_ntoh32(cpi->trap_qkey));
+}
+
+static void dump_portinfo_record(void *data, struct query_params *p)
+{
+ ib_portinfo_record_t *p_pir = data;
+ const ib_port_info_t *const p_pi = &p_pir->port_info;
+
+ printf("PortInfoRecord dump:\n"
+ "\t\tEndPortLid..............%u\n"
+ "\t\tPortNum.................%u\n"
+ "\t\tbase_lid................%u\n"
+ "\t\tmaster_sm_base_lid......%u\n"
+ "\t\tcapability_mask.........0x%X\n",
+ cl_ntoh16(p_pir->lid), p_pir->port_num,
+ cl_ntoh16(p_pi->base_lid), cl_ntoh16(p_pi->master_sm_base_lid),
+ cl_ntoh32(p_pi->capability_mask));
+}
+
+static void dump_one_portinfo_record(void *data, struct query_params *p)
+{
+ ib_portinfo_record_t *pir = data;
+ ib_port_info_t *pi = &pir->port_info;
+
+ printf("PortInfoRecord dump:\n"
+ "\tRID\n"
+ "\t\tEndPortLid..............%u\n"
+ "\t\tPortNum.................%u\n"
+ "\t\tOptions.................0x%x\n"
+ "\tPortInfo dump:\n",
+ cl_ntoh16(pir->lid), pir->port_num, pir->options);
+ dump_portinfo(pi, 2);
+}
+
+static void dump_one_mcmember_record(void *data, struct query_params *p)
+{
+ char mgid[INET6_ADDRSTRLEN], gid[INET6_ADDRSTRLEN];
+ ib_member_rec_t *mr = data;
+ uint32_t flow;
+ uint8_t sl, hop, scope, join;
+ ib_member_get_sl_flow_hop(mr->sl_flow_hop, &sl, &flow, &hop);
+ ib_member_get_scope_state(mr->scope_state, &scope, &join);
+ printf("MCMember Record dump:\n"
+ "\t\tMGID....................%s\n"
+ "\t\tPortGid.................%s\n"
+ "\t\tqkey....................0x%x\n"
+ "\t\tmlid....................0x%x\n"
+ "\t\tmtu.....................0x%x\n"
+ "\t\tTClass..................0x%x\n"
+ "\t\tpkey....................0x%x\n"
+ "\t\trate....................0x%x\n"
+ "\t\tpkt_life................0x%x\n"
+ "\t\tSL......................0x%x\n"
+ "\t\tFlowLabel...............0x%x\n"
+ "\t\tHopLimit................0x%x\n"
+ "\t\tScope...................0x%x\n"
+ "\t\tJoinState...............0x%x\n"
+ "\t\tProxyJoin...............0x%x\n",
+ inet_ntop(AF_INET6, mr->mgid.raw, mgid, sizeof(mgid)),
+ inet_ntop(AF_INET6, mr->port_gid.raw, gid, sizeof(gid)),
+ cl_ntoh32(mr->qkey), cl_ntoh16(mr->mlid), mr->mtu, mr->tclass,
+ cl_ntoh16(mr->pkey), mr->rate, mr->pkt_life, sl,
+ flow, hop, scope, join, mr->proxy_join);
+}
+
+static void dump_multicast_group_record(void *data, struct query_params *p)
+{
+ char gid_str[INET6_ADDRSTRLEN];
+ ib_member_rec_t *p_mcmr = data;
+ uint8_t sl;
+ ib_member_get_sl_flow_hop(p_mcmr->sl_flow_hop, &sl, NULL, NULL);
+ printf("MCMemberRecord group dump:\n"
+ "\t\tMGID....................%s\n"
+ "\t\tMlid....................0x%X\n"
+ "\t\tMtu.....................0x%X\n"
+ "\t\tpkey....................0x%X\n"
+ "\t\tRate....................0x%X\n"
+ "\t\tSL......................0x%X\n",
+ inet_ntop(AF_INET6, p_mcmr->mgid.raw, gid_str, sizeof gid_str),
+ cl_ntoh16(p_mcmr->mlid),
+ p_mcmr->mtu, cl_ntoh16(p_mcmr->pkey), p_mcmr->rate, sl);
+}
+
+static void dump_multicast_member_record(ib_member_rec_t *p_mcmr,
+ struct sa_query_result *nr_result,
+ struct query_params *params)
+{
+ char gid_str[INET6_ADDRSTRLEN];
+ char gid_str2[INET6_ADDRSTRLEN];
+ uint16_t mlid = cl_ntoh16(p_mcmr->mlid);
+ unsigned i = 0;
+ char *node_name = strdup("<unknown>");
+
+ /* go through the node records searching for a port guid which matches
+ * this port gid interface id.
+ * This gives us a node name to print, if available.
+ */
+ for (i = 0; i < nr_result->result_cnt; i++) {
+ ib_node_record_t *nr = sa_get_query_rec(nr_result->p_result_madw, i);
+ if (nr->node_info.port_guid ==
+ p_mcmr->port_gid.unicast.interface_id) {
+ if(node_name != NULL)
+ free(node_name);
+ node_name = remap_node_name(node_name_map,
+ nr->node_info.node_guid,
+ (char *)nr->node_desc.description);
+ break;
+ }
+ }
+
+ if (requested_name) {
+ if (strtol(requested_name, NULL, 0) == mlid)
+ printf("\t\tPortGid.................%s (%s)\n",
+ inet_ntop(AF_INET6, p_mcmr->port_gid.raw,
+ gid_str, sizeof gid_str), node_name);
+ } else {
+ printf("MCMemberRecord member dump:\n"
+ "\t\tMGID....................%s\n"
+ "\t\tMlid....................0x%X\n"
+ "\t\tPortGid.................%s\n"
+ "\t\tScopeState..............0x%X\n"
+ "\t\tProxyJoin...............0x%X\n"
+ "\t\tNodeDescription.........%s\n",
+ inet_ntop(AF_INET6, p_mcmr->mgid.raw, gid_str,
+ sizeof gid_str),
+ cl_ntoh16(p_mcmr->mlid),
+ inet_ntop(AF_INET6, p_mcmr->port_gid.raw,
+ gid_str2, sizeof gid_str2),
+ p_mcmr->scope_state, p_mcmr->proxy_join, node_name);
+ }
+ free(node_name);
+}
+
+static void dump_service_record(void *data, struct query_params *p)
+{
+ char gid[INET6_ADDRSTRLEN];
+ char buf_service_key[35];
+ char buf_service_name[65];
+ ib_service_record_t *p_sr = data;
+
+ sprintf(buf_service_key,
+ "0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+ p_sr->service_key[0], p_sr->service_key[1],
+ p_sr->service_key[2], p_sr->service_key[3],
+ p_sr->service_key[4], p_sr->service_key[5],
+ p_sr->service_key[6], p_sr->service_key[7],
+ p_sr->service_key[8], p_sr->service_key[9],
+ p_sr->service_key[10], p_sr->service_key[11],
+ p_sr->service_key[12], p_sr->service_key[13],
+ p_sr->service_key[14], p_sr->service_key[15]);
+ strncpy(buf_service_name, (char *)p_sr->service_name, 64);
+ buf_service_name[64] = '\0';
+
+ printf("ServiceRecord dump:\n"
+ "\t\tServiceID...............0x%016" PRIx64 "\n"
+ "\t\tServiceGID..............%s\n"
+ "\t\tServiceP_Key............0x%X\n"
+ "\t\tServiceLease............0x%X\n"
+ "\t\tServiceKey..............%s\n"
+ "\t\tServiceName.............%s\n"
+ "\t\tServiceData8.1..........0x%X\n"
+ "\t\tServiceData8.2..........0x%X\n"
+ "\t\tServiceData8.3..........0x%X\n"
+ "\t\tServiceData8.4..........0x%X\n"
+ "\t\tServiceData8.5..........0x%X\n"
+ "\t\tServiceData8.6..........0x%X\n"
+ "\t\tServiceData8.7..........0x%X\n"
+ "\t\tServiceData8.8..........0x%X\n"
+ "\t\tServiceData8.9..........0x%X\n"
+ "\t\tServiceData8.10.........0x%X\n"
+ "\t\tServiceData8.11.........0x%X\n"
+ "\t\tServiceData8.12.........0x%X\n"
+ "\t\tServiceData8.13.........0x%X\n"
+ "\t\tServiceData8.14.........0x%X\n"
+ "\t\tServiceData8.15.........0x%X\n"
+ "\t\tServiceData8.16.........0x%X\n"
+ "\t\tServiceData16.1.........0x%X\n"
+ "\t\tServiceData16.2.........0x%X\n"
+ "\t\tServiceData16.3.........0x%X\n"
+ "\t\tServiceData16.4.........0x%X\n"
+ "\t\tServiceData16.5.........0x%X\n"
+ "\t\tServiceData16.6.........0x%X\n"
+ "\t\tServiceData16.7.........0x%X\n"
+ "\t\tServiceData16.8.........0x%X\n"
+ "\t\tServiceData32.1.........0x%X\n"
+ "\t\tServiceData32.2.........0x%X\n"
+ "\t\tServiceData32.3.........0x%X\n"
+ "\t\tServiceData32.4.........0x%X\n"
+ "\t\tServiceData64.1.........0x%016" PRIx64 "\n"
+ "\t\tServiceData64.2.........0x%016" PRIx64 "\n",
+ cl_ntoh64(p_sr->service_id),
+ inet_ntop(AF_INET6, p_sr->service_gid.raw, gid, sizeof gid),
+ cl_ntoh16(p_sr->service_pkey), cl_ntoh32(p_sr->service_lease),
+ (show_keys ? buf_service_key : NOT_DISPLAYED_STR),
+ buf_service_name,
+ p_sr->service_data8[0], p_sr->service_data8[1],
+ p_sr->service_data8[2], p_sr->service_data8[3],
+ p_sr->service_data8[4], p_sr->service_data8[5],
+ p_sr->service_data8[6], p_sr->service_data8[7],
+ p_sr->service_data8[8], p_sr->service_data8[9],
+ p_sr->service_data8[10], p_sr->service_data8[11],
+ p_sr->service_data8[12], p_sr->service_data8[13],
+ p_sr->service_data8[14], p_sr->service_data8[15],
+ cl_ntoh16(p_sr->service_data16[0]),
+ cl_ntoh16(p_sr->service_data16[1]),
+ cl_ntoh16(p_sr->service_data16[2]),
+ cl_ntoh16(p_sr->service_data16[3]),
+ cl_ntoh16(p_sr->service_data16[4]),
+ cl_ntoh16(p_sr->service_data16[5]),
+ cl_ntoh16(p_sr->service_data16[6]),
+ cl_ntoh16(p_sr->service_data16[7]),
+ cl_ntoh32(p_sr->service_data32[0]),
+ cl_ntoh32(p_sr->service_data32[1]),
+ cl_ntoh32(p_sr->service_data32[2]),
+ cl_ntoh32(p_sr->service_data32[3]),
+ cl_ntoh64(p_sr->service_data64[0]),
+ cl_ntoh64(p_sr->service_data64[1]));
+}
+
+static void dump_sm_info_record(void *data, struct query_params *p)
+{
+ ib_sminfo_record_t *p_smr = data;
+ const ib_sm_info_t *const p_smi = &p_smr->sm_info;
+ uint8_t priority, state;
+ priority = ib_sminfo_get_priority(p_smi);
+ state = ib_sminfo_get_state(p_smi);
+
+ printf("SMInfoRecord dump:\n"
+ "\t\tRID\n"
+ "\t\tLID...................%u\n"
+ "\t\tSMInfo dump:\n"
+ "\t\tGUID..................0x%016" PRIx64 "\n"
+ "\t\tSM_Key................0x%016" PRIx64 "\n"
+ "\t\tActCount..............%u\n"
+ "\t\tPriority..............%u\n"
+ "\t\tSMState...............%u\n",
+ cl_ntoh16(p_smr->lid),
+ cl_ntoh64(p_smr->sm_info.guid),
+ cl_ntoh64(p_smr->sm_info.sm_key),
+ cl_ntoh32(p_smr->sm_info.act_count),
+ priority, state);
+}
+
+static void dump_switch_info_record(void *data, struct query_params *p)
+{
+ ib_switch_info_record_t *p_sir = data;
+ uint32_t sa_cap_mask2 = ib_class_cap_mask2(&p->cpi);
+
+ printf("SwitchInfoRecord dump:\n"
+ "\t\tRID\n"
+ "\t\tLID.....................................%u\n"
+ "\t\tSwitchInfo dump:\n"
+ "\t\tLinearFDBCap............................0x%X\n"
+ "\t\tRandomFDBCap............................0x%X\n"
+ "\t\tMulticastFDBCap.........................0x%X\n"
+ "\t\tLinearFDBTop............................0x%X\n"
+ "\t\tDefaultPort.............................%u\n"
+ "\t\tDefaultMulticastPrimaryPort.............%u\n"
+ "\t\tDefaultMulticastNotPrimaryPort..........%u\n"
+ "\t\tLifeTimeValue/PortStateChange/OpSL2VL...0x%X\n"
+ "\t\tLIDsPerPort.............................0x%X\n"
+ "\t\tPartitionEnforcementCap.................0x%X\n"
+ "\t\tflags...................................0x%X\n",
+ cl_ntoh16(p_sir->lid),
+ cl_ntoh16(p_sir->switch_info.lin_cap),
+ cl_ntoh16(p_sir->switch_info.rand_cap),
+ cl_ntoh16(p_sir->switch_info.mcast_cap),
+ cl_ntoh16(p_sir->switch_info.lin_top),
+ p_sir->switch_info.def_port,
+ p_sir->switch_info.def_mcast_pri_port,
+ p_sir->switch_info.def_mcast_not_port,
+ p_sir->switch_info.life_state,
+ cl_ntoh16(p_sir->switch_info.lids_per_port),
+ cl_ntoh16(p_sir->switch_info.enforce_cap),
+ p_sir->switch_info.flags);
+ if (sa_cap_mask2 & UMAD_SA_CAP_MASK2_IS_MCAST_TOP_SUP)
+ printf("\t\tMulticastFDBTop.........................0x%X\n",
+ cl_ntoh16(p_sir->switch_info.mcast_top));
+}
+
+static void dump_inform_info_record(void *data, struct query_params *p)
+{
+ char gid_str[INET6_ADDRSTRLEN];
+ char gid_str2[INET6_ADDRSTRLEN];
+ ib_inform_info_record_t *p_iir = data;
+ uint32_t qpn;
+ uint8_t resp_time_val;
+
+ ib_inform_info_get_qpn_resp_time(p_iir->inform_info.g_or_v.
+ generic.qpn_resp_time_val, &qpn,
+ &resp_time_val);
+ if (p_iir->inform_info.is_generic) {
+ printf("InformInfoRecord dump:\n"
+ "\t\tRID\n"
+ "\t\tSubscriberGID...........%s\n"
+ "\t\tSubscriberEnum..........0x%X\n"
+ "\t\tInformInfo dump:\n"
+ "\t\tgid.....................%s\n"
+ "\t\tlid_range_begin.........%u\n"
+ "\t\tlid_range_end...........%u\n"
+ "\t\tis_generic..............0x%X\n"
+ "\t\tsubscribe...............0x%X\n"
+ "\t\ttrap_type...............0x%X\n"
+ "\t\ttrap_num................%u\n",
+ inet_ntop(AF_INET6, p_iir->subscriber_gid.raw, gid_str,
+ sizeof gid_str),
+ cl_ntoh16(p_iir->subscriber_enum),
+ inet_ntop(AF_INET6, p_iir->inform_info.gid.raw, gid_str2,
+ sizeof gid_str2),
+ cl_ntoh16(p_iir->inform_info.lid_range_begin),
+ cl_ntoh16(p_iir->inform_info.lid_range_end),
+ p_iir->inform_info.is_generic,
+ p_iir->inform_info.subscribe,
+ cl_ntoh16(p_iir->inform_info.trap_type),
+ cl_ntoh16(p_iir->inform_info.g_or_v.generic.trap_num));
+ if (show_keys) {
+ printf("\t\tqpn.....................0x%06X\n",
+ cl_ntoh32(qpn));
+ } else {
+ printf("\t\tqpn....................."
+ NOT_DISPLAYED_STR "\n");
+ }
+ printf("\t\tresp_time_val...........0x%X\n"
+ "\t\tnode_type...............0x%06X\n",
+ resp_time_val,
+ cl_ntoh32(ib_inform_info_get_prod_type
+ (&p_iir->inform_info)));
+ } else {
+ printf("InformInfoRecord dump:\n"
+ "\t\tRID\n"
+ "\t\tSubscriberGID...........%s\n"
+ "\t\tSubscriberEnum..........0x%X\n"
+ "\t\tInformInfo dump:\n"
+ "\t\tgid.....................%s\n"
+ "\t\tlid_range_begin.........%u\n"
+ "\t\tlid_range_end...........%u\n"
+ "\t\tis_generic..............0x%X\n"
+ "\t\tsubscribe...............0x%X\n"
+ "\t\ttrap_type...............0x%X\n"
+ "\t\tdev_id..................0x%X\n",
+ inet_ntop(AF_INET6, p_iir->subscriber_gid.raw, gid_str,
+ sizeof gid_str),
+ cl_ntoh16(p_iir->subscriber_enum),
+ inet_ntop(AF_INET6, p_iir->inform_info.gid.raw,
+ gid_str2, sizeof gid_str2),
+ cl_ntoh16(p_iir->inform_info.lid_range_begin),
+ cl_ntoh16(p_iir->inform_info.lid_range_end),
+ p_iir->inform_info.is_generic,
+ p_iir->inform_info.subscribe,
+ cl_ntoh16(p_iir->inform_info.trap_type),
+ cl_ntoh16(p_iir->inform_info.g_or_v.vend.dev_id));
+ if (show_keys) {
+ printf("\t\tqpn.....................0x%06X\n",
+ cl_ntoh32(qpn));
+ } else {
+ printf("\t\tqpn....................."
+ NOT_DISPLAYED_STR "\n");
+ }
+ printf("\t\tresp_time_val...........0x%X\n"
+ "\t\tvendor_id...............0x%06X\n",
+ resp_time_val,
+ cl_ntoh32(ib_inform_info_get_prod_type
+ (&p_iir->inform_info)));
+ }
+}
+
+static void dump_one_link_record(void *data, struct query_params *p)
+{
+ ib_link_record_t *lr = data;
+ printf("LinkRecord dump:\n"
+ "\t\tFromLID....................%u\n"
+ "\t\tFromPort...................%u\n"
+ "\t\tToPort.....................%u\n"
+ "\t\tToLID......................%u\n",
+ cl_ntoh16(lr->from_lid), lr->from_port_num,
+ lr->to_port_num, cl_ntoh16(lr->to_lid));
+}
+
+static void dump_one_slvl_record(void *data, struct query_params *p)
+{
+ ib_slvl_table_record_t *slvl = data;
+ ib_slvl_table_t *t = &slvl->slvl_tbl;
+ printf("SL2VLTableRecord dump:\n"
+ "\t\tLID........................%u\n"
+ "\t\tInPort.....................%u\n"
+ "\t\tOutPort....................%u\n"
+ "\t\tSL: 0| 1| 2| 3| 4| 5| 6| 7| 8| 9|10|11|12|13|14|15|\n"
+ "\t\tVL:%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u"
+ "|%2u|%2u|%2u|\n",
+ cl_ntoh16(slvl->lid), slvl->in_port_num, slvl->out_port_num,
+ ib_slvl_table_get(t, 0), ib_slvl_table_get(t, 1),
+ ib_slvl_table_get(t, 2), ib_slvl_table_get(t, 3),
+ ib_slvl_table_get(t, 4), ib_slvl_table_get(t, 5),
+ ib_slvl_table_get(t, 6), ib_slvl_table_get(t, 7),
+ ib_slvl_table_get(t, 8), ib_slvl_table_get(t, 9),
+ ib_slvl_table_get(t, 10), ib_slvl_table_get(t, 11),
+ ib_slvl_table_get(t, 12), ib_slvl_table_get(t, 13),
+ ib_slvl_table_get(t, 14), ib_slvl_table_get(t, 15));
+}
+
+static void dump_one_vlarb_record(void *data, struct query_params *p)
+{
+ ib_vl_arb_table_record_t *vlarb = data;
+ ib_vl_arb_element_t *e = vlarb->vl_arb_tbl.vl_entry;
+ int i;
+ printf("VLArbTableRecord dump:\n"
+ "\t\tLID........................%u\n"
+ "\t\tPort.......................%u\n"
+ "\t\tBlock......................%u\n",
+ cl_ntoh16(vlarb->lid), vlarb->port_num, vlarb->block_num);
+ for (i = 0; i < 32; i += 16)
+ printf("\t\tVL :%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u|"
+ "%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u|\n"
+ "\t\tWeight:%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u|"
+ "%2u|%2u|%2u|%2u|%2u|%2u|%2u|%2u|\n",
+ e[i + 0].vl, e[i + 1].vl, e[i + 2].vl, e[i + 3].vl,
+ e[i + 4].vl, e[i + 5].vl, e[i + 6].vl, e[i + 7].vl,
+ e[i + 8].vl, e[i + 9].vl, e[i + 10].vl, e[i + 11].vl,
+ e[i + 12].vl, e[i + 13].vl, e[i + 14].vl, e[i + 15].vl,
+ e[i + 0].weight, e[i + 1].weight, e[i + 2].weight,
+ e[i + 3].weight, e[i + 4].weight, e[i + 5].weight,
+ e[i + 6].weight, e[i + 7].weight, e[i + 8].weight,
+ e[i + 9].weight, e[i + 10].weight, e[i + 11].weight,
+ e[i + 12].weight, e[i + 13].weight, e[i + 14].weight,
+ e[i + 15].weight);
+}
+
+static void dump_one_pkey_tbl_record(void *data, struct query_params *params)
+{
+ ib_pkey_table_record_t *pktr = data;
+ ib_net16_t *p = pktr->pkey_tbl.pkey_entry;
+ int i;
+ printf("PKeyTableRecord dump:\n"
+ "\t\tLID........................%u\n"
+ "\t\tPort.......................%u\n"
+ "\t\tBlock......................%u\n"
+ "\t\tPKey Table:\n",
+ cl_ntoh16(pktr->lid), pktr->port_num, pktr->block_num);
+ for (i = 0; i < 32; i += 8)
+ printf("\t\t0x%04x 0x%04x 0x%04x 0x%04x"
+ " 0x%04x 0x%04x 0x%04x 0x%04x\n",
+ cl_ntoh16(p[i + 0]), cl_ntoh16(p[i + 1]),
+ cl_ntoh16(p[i + 2]), cl_ntoh16(p[i + 3]),
+ cl_ntoh16(p[i + 4]), cl_ntoh16(p[i + 5]),
+ cl_ntoh16(p[i + 6]), cl_ntoh16(p[i + 7]));
+ printf("\n");
+}
+
+static void dump_one_lft_record(void *data, struct query_params *p)
+{
+ ib_lft_record_t *lftr = data;
+ unsigned block = cl_ntoh16(lftr->block_num);
+ int i;
+ printf("LFT Record dump:\n"
+ "\t\tLID........................%u\n"
+ "\t\tBlock......................%u\n"
+ "\t\tLFT:\n\t\tLID\tPort Number\n", cl_ntoh16(lftr->lid), block);
+ for (i = 0; i < 64; i++)
+ printf("\t\t%u\t%u\n", block * 64 + i, lftr->lft[i]);
+ printf("\n");
+}
+
+static void dump_one_guidinfo_record(void *data, struct query_params *p)
+{
+ ib_guidinfo_record_t *gir = data;
+ printf("GUIDInfo Record dump:\n"
+ "\t\tLID........................%u\n"
+ "\t\tBlock......................%u\n"
+ "\t\tGUID 0.....................0x%016" PRIx64 "\n"
+ "\t\tGUID 1.....................0x%016" PRIx64 "\n"
+ "\t\tGUID 2.....................0x%016" PRIx64 "\n"
+ "\t\tGUID 3.....................0x%016" PRIx64 "\n"
+ "\t\tGUID 4.....................0x%016" PRIx64 "\n"
+ "\t\tGUID 5.....................0x%016" PRIx64 "\n"
+ "\t\tGUID 6.....................0x%016" PRIx64 "\n"
+ "\t\tGUID 7.....................0x%016" PRIx64 "\n",
+ cl_ntoh16(gir->lid), gir->block_num,
+ cl_ntoh64(gir->guid_info.guid[0]),
+ cl_ntoh64(gir->guid_info.guid[1]),
+ cl_ntoh64(gir->guid_info.guid[2]),
+ cl_ntoh64(gir->guid_info.guid[3]),
+ cl_ntoh64(gir->guid_info.guid[4]),
+ cl_ntoh64(gir->guid_info.guid[5]),
+ cl_ntoh64(gir->guid_info.guid[6]),
+ cl_ntoh64(gir->guid_info.guid[7]));
+}
+
+static void dump_one_mft_record(void *data, struct query_params *p)
+{
+ ib_mft_record_t *mftr = data;
+ unsigned position = cl_ntoh16(mftr->position_block_num) >> 12;
+ unsigned block = cl_ntoh16(mftr->position_block_num) &
+ IB_MCAST_BLOCK_ID_MASK_HO;
+ int i;
+ unsigned offset;
+
+ printf("MFT Record dump:\n"
+ "\t\tLID........................%u\n"
+ "\t\tPosition...................%u\n"
+ "\t\tBlock......................%u\n"
+ "\t\tMFT:\n\t\tMLID\tPort Mask\n",
+ cl_ntoh16(mftr->lid), position, block);
+ offset = IB_LID_MCAST_START_HO + block * 32;
+ for (i = 0; i < IB_MCAST_BLOCK_SIZE; i++)
+ printf("\t\t0x%04x\t0x%04x\n",
+ offset + i, cl_ntoh16(mftr->mft[i]));
+ printf("\n");
+}
+
+static void dump_results(struct sa_query_result *r,
+ void (*dump_func) (void *, struct query_params *),
+ struct query_params *p)
+{
+ unsigned i;
+ for (i = 0; i < r->result_cnt; i++) {
+ void *data = sa_get_query_rec(r->p_result_madw, i);
+ dump_func(data, p);
+ }
+}
+
+/**
+ * Get any record(s)
+ */
+static int get_any_records(struct sa_handle * h,
+ uint16_t attr_id, uint32_t attr_mod,
+ ib_net64_t comp_mask, void *attr,
+ size_t attr_size,
+ struct sa_query_result *result)
+{
+ int ret = sa_query(h, IB_MAD_METHOD_GET_TABLE, attr_id, attr_mod,
+ cl_ntoh64(comp_mask), ibd_sakey, attr, attr_size, result);
+ if (ret) {
+ fprintf(stderr, "Query SA failed: %s\n", strerror(ret));
+ return ret;
+ }
+
+ if (result->status != IB_SA_MAD_STATUS_SUCCESS) {
+ sa_report_err(result->status);
+ return EIO;
+ }
+
+ return ret;
+}
+
+static int get_and_dump_any_records(struct sa_handle * h, uint16_t attr_id,
+ uint32_t attr_mod, ib_net64_t comp_mask,
+ void *attr,
+ size_t attr_size,
+ void (*dump_func) (void *,
+ struct query_params *),
+ struct query_params *p)
+{
+ struct sa_query_result result;
+ int ret = get_any_records(h, attr_id, attr_mod, comp_mask, attr,
+ attr_size, &result);
+ if (ret)
+ return ret;
+
+ dump_results(&result, dump_func, p);
+ sa_free_result_mad(&result);
+ return 0;
+}
+
+/**
+ * Get all the records available for requested query type.
+ */
+static int get_all_records(struct sa_handle * h, uint16_t attr_id,
+ struct sa_query_result *result)
+{
+ return get_any_records(h, attr_id, 0, 0, NULL, 0, result);
+}
+
+static int get_and_dump_all_records(struct sa_handle * h, uint16_t attr_id,
+ void (*dump_func) (void *,
+ struct query_params *p),
+ struct query_params *p)
+{
+ struct sa_query_result result;
+ int ret = get_all_records(h, attr_id, &result);
+ if (ret)
+ return ret;
+
+ dump_results(&result, dump_func, p);
+ sa_free_result_mad(&result);
+ return ret;
+}
+
+/**
+ * return the lid from the node descriptor (name) supplied
+ */
+static int get_lid_from_name(struct sa_handle * h, const char *name, uint16_t * lid)
+{
+ ib_node_record_t *node_record = NULL;
+ unsigned i;
+ int ret;
+ struct sa_query_result result;
+
+ ret = get_all_records(h, IB_SA_ATTR_NODERECORD, &result);
+ if (ret)
+ return ret;
+
+ ret = EHOSTDOWN;
+ for (i = 0; i < result.result_cnt; i++) {
+ node_record = sa_get_query_rec(result.p_result_madw, i);
+ if (name
+ && strncmp(name, (char *)node_record->node_desc.description,
+ sizeof(node_record->node_desc.description)) ==
+ 0) {
+ *lid = cl_ntoh16(node_record->lid);
+ ret = 0;
+ break;
+ }
+ }
+ sa_free_result_mad(&result);
+ return ret;
+}
+
+static uint16_t get_lid(struct sa_handle * h, const char *name)
+{
+ int rc = 0;
+ uint16_t rc_lid = 0;
+
+ if (!name)
+ return 0;
+ if (isalpha(name[0])) {
+ if ((rc = get_lid_from_name(h, name, &rc_lid)) != 0) {
+ fprintf(stderr, "Failed to find lid for \"%s\": %s\n",
+ name, strerror(rc));
+ exit(rc);
+ }
+ } else {
+ long val;
+ errno = 0;
+ val = strtol(name, NULL, 0);
+ if (errno != 0 || val <= 0 || val > UINT16_MAX) {
+ fprintf(stderr, "Invalid lid specified: \"%s\"\n", name);
+ exit(EINVAL);
+ }
+ rc_lid = (uint16_t)val;
+ }
+
+ return rc_lid;
+}
+
+static int parse_iir_subscriber_gid(char *str, ib_inform_info_record_t *ir)
+{
+ int rc = inet_pton(AF_INET6,str,&(ir->subscriber_gid.raw));
+ if(rc < 1){
+ fprintf(stderr, "Invalid SubscriberGID specified: \"%s\"\n",str);
+ exit(EINVAL);
+ }
+ return rc;
+}
+
+static int parse_lid_and_ports(struct sa_handle * h,
+ char *str, int *lid, int *port1, int *port2)
+{
+ char *p, *e;
+
+ if (port1)
+ *port1 = -1;
+ if (port2)
+ *port2 = -1;
+
+ p = strchr(str, '/');
+ if (p)
+ *p = '\0';
+ if (lid)
+ *lid = get_lid(h, str);
+
+ if (!p)
+ return 0;
+ str = p + 1;
+ p = strchr(str, '/');
+ if (p)
+ *p = '\0';
+ if (port1) {
+ *port1 = strtoul(str, &e, 0);
+ if (e == str)
+ *port1 = -1;
+ }
+
+ if (!p)
+ return 0;
+ str = p + 1;
+ if (port2) {
+ *port2 = strtoul(str, &e, 0);
+ if (e == str)
+ *port2 = -1;
+ }
+
+ return 0;
+}
+
+/*
+ * Get the portinfo records available with IsSM or IsSMdisabled CapabilityMask bit on.
+ */
+static int get_issm_records(struct sa_handle * h, ib_net32_t capability_mask,
+ struct sa_query_result *result)
+{
+ ib_portinfo_record_t attr;
+
+ memset(&attr, 0, sizeof(attr));
+ attr.port_info.capability_mask = capability_mask;
+
+ return get_any_records(h, IB_SA_ATTR_PORTINFORECORD, 1 << 31,
+ IB_PIR_COMPMASK_CAPMASK, &attr, sizeof(attr), result);
+}
+
+static int print_node_records(struct sa_handle * h, struct query_params *p)
+{
+ unsigned i;
+ int ret;
+ struct sa_query_result result;
+
+ ret = get_all_records(h, IB_SA_ATTR_NODERECORD, &result);
+ if (ret)
+ return ret;
+
+ if (node_print_desc == ALL_DESC) {
+ printf(" LID \"name\"\n");
+ printf("================\n");
+ }
+ for (i = 0; i < result.result_cnt; i++) {
+ ib_node_record_t *node_record;
+ node_record = sa_get_query_rec(result.p_result_madw, i);
+ if (node_print_desc == ALL_DESC) {
+ print_node_desc(node_record);
+ } else if (node_print_desc == NAME_OF_LID) {
+ if (requested_lid == cl_ntoh16(node_record->lid))
+ print_node_record(node_record);
+ } else if (node_print_desc == NAME_OF_GUID) {
+ ib_node_info_t *p_ni = &(node_record->node_info);
+
+ if (requested_guid == cl_ntoh64(p_ni->port_guid))
+ print_node_record(node_record);
+ } else {
+ ib_node_info_t *p_ni = &(node_record->node_info);
+ ib_node_desc_t *p_nd = &(node_record->node_desc);
+ char *name;
+
+ name = remap_node_name (node_name_map,
+ cl_ntoh64(p_ni->node_guid),
+ (char *)p_nd->description);
+
+ if (!requested_name ||
+ (strncmp(requested_name,
+ (char *)node_record->node_desc.description,
+ sizeof(node_record->
+ node_desc.description)) == 0) ||
+ (strncmp(requested_name,
+ name,
+ sizeof(node_record->
+ node_desc.description)) == 0)) {
+ print_node_record(node_record);
+ if (node_print_desc == UNIQUE_LID_ONLY) {
+ sa_free_result_mad(&result);
+ exit(0);
+ }
+ }
+
+ free(name);
+ }
+ }
+ sa_free_result_mad(&result);
+ return ret;
+}
+
+static int sm_pr_query(struct sa_handle * h, ibmad_gid_t *gid, int srclid, int destlid) {
+
+ ib_path_rec_t pr;
+ ib_net64_t comp_mask = 0;
+ struct sa_query_result result;
+ int ret;
+ ib_path_rec_t *p_pr;
+
+ memset(&pr, 0, sizeof(pr));
+ CHECK_AND_SET_VAL(srclid, 16, 0, pr.slid, PR, SLID);
+ CHECK_AND_SET_VAL(destlid, 16, 0, pr.dlid, PR, DLID);
+
+ ret = get_any_records(h, IB_SA_ATTR_PATHRECORD, 0, comp_mask, &pr, sizeof(pr), &result);
+ if (ret)
+ return ret;
+
+ p_pr = sa_get_query_rec(result.p_result_madw, 0);
+ memcpy(gid, &p_pr->dgid, 16);
+ sa_free_result_mad(&result);
+ return ret;
+}
+
+static int query_path_records(const struct query_cmd *q, struct sa_handle * h,
+ struct query_params *p, int argc, char *argv[])
+{
+ ib_path_rec_t pr;
+ ib_net64_t comp_mask = 0;
+ uint32_t flow = 0;
+ uint16_t qos_class = 0;
+ uint8_t reversible = 0;
+
+ memset(&pr, 0, sizeof(pr));
+ CHECK_AND_SET_VAL(p->service_id, 64, 0, pr.service_id, PR, SERVICEID);
+ CHECK_AND_SET_GID(p->sgid, pr.sgid, PR, SGID);
+ CHECK_AND_SET_GID(p->dgid, pr.dgid, PR, DGID);
+ CHECK_AND_SET_VAL(p->slid, 16, 0, pr.slid, PR, SLID);
+ CHECK_AND_SET_VAL(p->dlid, 16, 0, pr.dlid, PR, DLID);
+ CHECK_AND_SET_VAL(p->hop_limit, 32, -1, pr.hop_flow_raw, PR, HOPLIMIT);
+ CHECK_AND_SET_VAL((p->flow_label << 8), 32, 0, flow, PR, FLOWLABEL);
+ pr.hop_flow_raw =
+ (pr.hop_flow_raw & cl_hton32(~0x0FFFFF00)) | flow;
+ CHECK_AND_SET_VAL(p->tclass, 8, 0, pr.tclass, PR, TCLASS);
+ CHECK_AND_SET_VAL(p->reversible, 8, -1, reversible, PR, REVERSIBLE);
+ CHECK_AND_SET_VAL(p->numb_path, 8, -1, pr.num_path, PR, NUMBPATH);
+ pr.num_path |= reversible << 7;
+ CHECK_AND_SET_VAL(p->pkey, 16, 0, pr.pkey, PR, PKEY);
+ CHECK_AND_SET_VAL(p->sl, 16, -1, pr.qos_class_sl, PR, SL);
+ CHECK_AND_SET_VAL((p->qos_class << 4), 16, -1, qos_class, PR, QOS_CLASS);
+ pr.qos_class_sl = (pr.qos_class_sl & CL_HTON16(IB_PATH_REC_SL_MASK)) |
+ qos_class;
+ CHECK_AND_SET_VAL_AND_SEL(p->mtu, pr.mtu, PR, MTU, SELEC);
+ CHECK_AND_SET_VAL_AND_SEL(p->rate, pr.rate, PR, RATE, SELEC);
+ CHECK_AND_SET_VAL_AND_SEL(p->pkt_life, pr.pkt_life, PR, PKTLIFETIME,
+ SELEC);
+
+ return get_and_dump_any_records(h, IB_SA_ATTR_PATHRECORD, 0, comp_mask,
+ &pr, sizeof(pr), dump_path_record, p);
+}
+
+static int print_issm_records(struct sa_handle * h, struct query_params *p)
+{
+ struct sa_query_result result;
+ int ret = 0;
+
+ /* First, get IsSM records */
+ ret = get_issm_records(h, IB_PORT_CAP_IS_SM, &result);
+ if (ret != 0)
+ return (ret);
+
+ printf("IsSM ports\n");
+ dump_results(&result, dump_portinfo_record, p);
+ sa_free_result_mad(&result);
+
+ /* Now, get IsSMdisabled records */
+ ret = get_issm_records(h, IB_PORT_CAP_SM_DISAB, &result);
+ if (ret != 0)
+ return (ret);
+
+ printf("\nIsSMdisabled ports\n");
+ dump_results(&result, dump_portinfo_record, p);
+ sa_free_result_mad(&result);
+
+ return (ret);
+}
+
+static int print_multicast_member_records(struct sa_handle * h,
+ struct query_params *params)
+{
+ struct sa_query_result mc_group_result;
+ struct sa_query_result nr_result;
+ int ret;
+ unsigned i;
+
+ ret = get_all_records(h, IB_SA_ATTR_MCRECORD, &mc_group_result);
+ if (ret)
+ return ret;
+
+ ret = get_all_records(h, IB_SA_ATTR_NODERECORD, &nr_result);
+ if (ret)
+ goto return_mc;
+
+ for (i = 0; i < mc_group_result.result_cnt; i++) {
+ ib_member_rec_t *rec = (ib_member_rec_t *)
+ sa_get_query_rec(mc_group_result.p_result_madw,
+ i);
+ dump_multicast_member_record(rec, &nr_result, params);
+ }
+
+ sa_free_result_mad(&nr_result);
+
+return_mc:
+ sa_free_result_mad(&mc_group_result);
+
+ return ret;
+}
+
+static int print_multicast_group_records(struct sa_handle * h,
+ struct query_params *p)
+{
+ return get_and_dump_all_records(h, IB_SA_ATTR_MCRECORD,
+ dump_multicast_group_record, p);
+}
+
+static int query_class_port_info(const struct query_cmd *q, struct sa_handle * h,
+ struct query_params *p, int argc, char *argv[])
+{
+ dump_class_port_info(&p->cpi);
+ return (0);
+}
+
+static int query_node_records(const struct query_cmd *q, struct sa_handle * h,
+ struct query_params *p, int argc, char *argv[])
+{
+ ib_node_record_t nr;
+ ib_net64_t comp_mask = 0;
+ int lid = 0;
+
+ if (argc > 0)
+ parse_lid_and_ports(h, argv[0], &lid, NULL, NULL);
+
+ memset(&nr, 0, sizeof(nr));
+ CHECK_AND_SET_VAL(lid, 16, 0, nr.lid, NR, LID);
+
+ return get_and_dump_any_records(h, IB_SA_ATTR_NODERECORD, 0, comp_mask,
+ &nr, sizeof(nr), dump_node_record, p);
+}
+
+static int query_portinfo_records(const struct query_cmd *q,
+ struct sa_handle * h, struct query_params *p,
+ int argc, char *argv[])
+{
+ ib_portinfo_record_t pir;
+ ib_net64_t comp_mask = 0;
+ int lid = 0, port = -1, options = -1;
+
+ if (argc > 0)
+ parse_lid_and_ports(h, argv[0], &lid, &port, &options);
+
+ memset(&pir, 0, sizeof(pir));
+ CHECK_AND_SET_VAL(lid, 16, 0, pir.lid, PIR, LID);
+ CHECK_AND_SET_VAL(port, 8, -1, pir.port_num, PIR, PORTNUM);
+ CHECK_AND_SET_VAL(options, 8, -1, pir.options, PIR, OPTIONS);
+
+ return get_and_dump_any_records(h, IB_SA_ATTR_PORTINFORECORD, 0,
+ comp_mask, &pir, sizeof(pir),
+ dump_one_portinfo_record, p);
+}
+
+static int query_mcmember_records(const struct query_cmd *q,
+ struct sa_handle * h, struct query_params *p,
+ int argc, char *argv[])
+{
+ ib_member_rec_t mr;
+ ib_net64_t comp_mask = 0;
+ uint32_t flow = 0;
+ uint8_t sl = 0, hop = 0, scope = 0;
+
+ memset(&mr, 0, sizeof(mr));
+ CHECK_AND_SET_GID(p->mgid, mr.mgid, MCR, MGID);
+ CHECK_AND_SET_GID(p->gid, mr.port_gid, MCR, PORT_GID);
+ CHECK_AND_SET_VAL(p->mlid, 16, 0, mr.mlid, MCR, MLID);
+ CHECK_AND_SET_VAL(p->qkey, 32, 0, mr.qkey, MCR, QKEY);
+ CHECK_AND_SET_VAL_AND_SEL(p->mtu, mr.mtu, MCR, MTU, _SEL);
+ CHECK_AND_SET_VAL_AND_SEL(p->rate, mr.rate, MCR, RATE, _SEL);
+ CHECK_AND_SET_VAL_AND_SEL(p->pkt_life, mr.pkt_life, MCR, LIFE, _SEL);
+ CHECK_AND_SET_VAL(p->tclass, 8, 0, mr.tclass, MCR, TCLASS);
+ CHECK_AND_SET_VAL(p->pkey, 16, 0, mr.pkey, MCR, PKEY);
+ CHECK_AND_SET_VAL(p->sl, 8, -1, sl, MCR, SL);
+ CHECK_AND_SET_VAL(p->flow_label, 32, 0, flow, MCR, FLOW);
+ CHECK_AND_SET_VAL(p->hop_limit, 8, 0, hop, MCR, HOP);
+ /* pass flow in host order as expected by function */
+ mr.sl_flow_hop = ib_member_set_sl_flow_hop(sl, cl_ntoh32(flow), hop);
+ CHECK_AND_SET_VAL(p->scope, 8, 0, scope, MCR, SCOPE);
+ CHECK_AND_SET_VAL(p->join_state, 8, 0, mr.scope_state, MCR, JOIN_STATE);
+ mr.scope_state |= scope << 4;
+ CHECK_AND_SET_VAL(p->proxy_join, 8, -1, mr.proxy_join, MCR, PROXY);
+
+ return get_and_dump_any_records(h, IB_SA_ATTR_MCRECORD, 0, comp_mask,
+ &mr, sizeof(mr), dump_one_mcmember_record, p);
+}
+
+static int query_service_records(const struct query_cmd *q, struct sa_handle * h,
+ struct query_params *p, int argc, char *argv[])
+{
+ return get_and_dump_all_records(h, IB_SA_ATTR_SERVICERECORD,
+ dump_service_record, p);
+}
+
+static int query_sm_info_records(const struct query_cmd *q,
+ struct sa_handle * h, struct query_params *p,
+ int argc, char *argv[])
+{
+ ib_sminfo_record_t smir;
+ ib_net64_t comp_mask = 0;
+ int lid = 0;
+
+ if (argc > 0)
+ parse_lid_and_ports(h, argv[0], &lid, NULL, NULL);
+
+ memset(&smir, 0, sizeof(smir));
+ CHECK_AND_SET_VAL(lid, 16, 0, smir.lid, SMIR, LID);
+
+ return get_and_dump_any_records(h, IB_SA_ATTR_SMINFORECORD, 0,
+ comp_mask, &smir, sizeof(smir),
+ dump_sm_info_record, p);
+}
+
+static int query_switchinfo_records(const struct query_cmd *q,
+ struct sa_handle * h, struct query_params *p,
+ int argc, char *argv[])
+{
+ ib_switch_info_record_t swir;
+ ib_net64_t comp_mask = 0;
+ int lid = 0;
+
+ if (argc > 0)
+ parse_lid_and_ports(h, argv[0], &lid, NULL, NULL);
+
+ memset(&swir, 0, sizeof(swir));
+ CHECK_AND_SET_VAL(lid, 16, 0, swir.lid, SWIR, LID);
+
+ return get_and_dump_any_records(h, IB_SA_ATTR_SWITCHINFORECORD, 0,
+ comp_mask, &swir, sizeof(swir),
+ dump_switch_info_record, p);
+}
+
+static int query_inform_info_records(const struct query_cmd *q,
+ struct sa_handle * h, struct query_params *p,
+ int argc, char *argv[])
+{
+ int rc = 0;
+ ib_inform_info_record_t ir;
+ ib_net64_t comp_mask = 0;
+ memset(&ir, 0, sizeof(ir));
+
+ if (argc > 0) {
+ comp_mask = IB_IIR_COMPMASK_SUBSCRIBERGID;
+ if((rc = parse_iir_subscriber_gid(argv[0], &ir)) < 1)
+ return rc;
+ }
+
+ return get_and_dump_any_records(h, IB_SA_ATTR_INFORMINFORECORD, 0, comp_mask,
+ &ir, sizeof(ir), dump_inform_info_record, p);
+
+}
+
+static int query_link_records(const struct query_cmd *q, struct sa_handle * h,
+ struct query_params *p, int argc, char *argv[])
+{
+ ib_link_record_t lr;
+ ib_net64_t comp_mask = 0;
+ int from_lid = 0, to_lid = 0, from_port = -1, to_port = -1;
+
+ if (argc > 0)
+ parse_lid_and_ports(h, argv[0], &from_lid, &from_port, NULL);
+
+ if (argc > 1)
+ parse_lid_and_ports(h, argv[1], &to_lid, &to_port, NULL);
+
+ memset(&lr, 0, sizeof(lr));
+ CHECK_AND_SET_VAL(from_lid, 16, 0, lr.from_lid, LR, FROM_LID);
+ CHECK_AND_SET_VAL(from_port, 8, -1, lr.from_port_num, LR, FROM_PORT);
+ CHECK_AND_SET_VAL(to_lid, 16, 0, lr.to_lid, LR, TO_LID);
+ CHECK_AND_SET_VAL(to_port, 8, -1, lr.to_port_num, LR, TO_PORT);
+
+ return get_and_dump_any_records(h, IB_SA_ATTR_LINKRECORD, 0, comp_mask,
+ &lr, sizeof(lr), dump_one_link_record, p);
+}
+
+static int query_sl2vl_records(const struct query_cmd *q, struct sa_handle * h,
+ struct query_params *p, int argc, char *argv[])
+{
+ ib_slvl_table_record_t slvl;
+ ib_net64_t comp_mask = 0;
+ int lid = 0, in_port = -1, out_port = -1;
+
+ if (argc > 0)
+ parse_lid_and_ports(h, argv[0], &lid, &in_port, &out_port);
+
+ memset(&slvl, 0, sizeof(slvl));
+ CHECK_AND_SET_VAL(lid, 16, 0, slvl.lid, SLVL, LID);
+ CHECK_AND_SET_VAL(in_port, 8, -1, slvl.in_port_num, SLVL, IN_PORT);
+ CHECK_AND_SET_VAL(out_port, 8, -1, slvl.out_port_num, SLVL, OUT_PORT);
+
+ return get_and_dump_any_records(h, IB_SA_ATTR_SL2VLTABLERECORD, 0,
+ comp_mask, &slvl, sizeof(slvl),
+ dump_one_slvl_record, p);
+}
+
+static int query_vlarb_records(const struct query_cmd *q, struct sa_handle * h,
+ struct query_params *p, int argc, char *argv[])
+{
+ ib_vl_arb_table_record_t vlarb;
+ ib_net64_t comp_mask = 0;
+ int lid = 0, port = -1, block = -1;
+
+ if (argc > 0)
+ parse_lid_and_ports(h, argv[0], &lid, &port, &block);
+
+ memset(&vlarb, 0, sizeof(vlarb));
+ CHECK_AND_SET_VAL(lid, 16, 0, vlarb.lid, VLA, LID);
+ CHECK_AND_SET_VAL(port, 8, -1, vlarb.port_num, VLA, OUT_PORT);
+ CHECK_AND_SET_VAL(block, 8, -1, vlarb.block_num, VLA, BLOCK);
+
+ return get_and_dump_any_records(h, IB_SA_ATTR_VLARBTABLERECORD, 0,
+ comp_mask, &vlarb, sizeof(vlarb),
+ dump_one_vlarb_record, p);
+}
+
+static int query_pkey_tbl_records(const struct query_cmd *q,
+ struct sa_handle * h, struct query_params *p,
+ int argc, char *argv[])
+{
+ ib_pkey_table_record_t pktr;
+ ib_net64_t comp_mask = 0;
+ int lid = 0, port = -1, block = -1;
+
+ if (argc > 0)
+ parse_lid_and_ports(h, argv[0], &lid, &port, &block);
+
+ memset(&pktr, 0, sizeof(pktr));
+ CHECK_AND_SET_VAL(lid, 16, 0, pktr.lid, PKEY, LID);
+ CHECK_AND_SET_VAL(port, 8, -1, pktr.port_num, PKEY, PORT);
+ CHECK_AND_SET_VAL(block, 16, -1, pktr.block_num, PKEY, BLOCK);
+
+ return get_and_dump_any_records(h, IB_SA_ATTR_PKEYTABLERECORD, 0,
+ comp_mask, &pktr, sizeof(pktr),
+ dump_one_pkey_tbl_record, p);
+}
+
+static int query_lft_records(const struct query_cmd *q, struct sa_handle * h,
+ struct query_params *p, int argc, char *argv[])
+{
+ ib_lft_record_t lftr;
+ ib_net64_t comp_mask = 0;
+ int lid = 0, block = -1;
+
+ if (argc > 0)
+ parse_lid_and_ports(h, argv[0], &lid, &block, NULL);
+
+ memset(&lftr, 0, sizeof(lftr));
+ CHECK_AND_SET_VAL(lid, 16, 0, lftr.lid, LFTR, LID);
+ CHECK_AND_SET_VAL(block, 16, -1, lftr.block_num, LFTR, BLOCK);
+
+ return get_and_dump_any_records(h, IB_SA_ATTR_LFTRECORD, 0, comp_mask,
+ &lftr, sizeof(lftr), dump_one_lft_record, p);
+}
+
+static int query_guidinfo_records(const struct query_cmd *q, struct sa_handle * h,
+ struct query_params *p, int argc, char *argv[])
+{
+ ib_guidinfo_record_t gir;
+ ib_net64_t comp_mask = 0;
+ int lid = 0, block = -1;
+
+ if (argc > 0)
+ parse_lid_and_ports(h, argv[0], &lid, &block, NULL);
+
+ memset(&gir, 0, sizeof(gir));
+ CHECK_AND_SET_VAL(lid, 16, 0, gir.lid, GIR, LID);
+ CHECK_AND_SET_VAL(block, 8, -1, gir.block_num, GIR, BLOCKNUM);
+
+ return get_and_dump_any_records(h, IB_SA_ATTR_GUIDINFORECORD, 0,
+ comp_mask, &gir, sizeof(gir),
+ dump_one_guidinfo_record, p);
+}
+
+static int query_mft_records(const struct query_cmd *q, struct sa_handle * h,
+ struct query_params *p, int argc, char *argv[])
+{
+ ib_mft_record_t mftr;
+ ib_net64_t comp_mask = 0;
+ int lid = 0, block = -1, position = -1;
+ uint16_t pos = 0;
+
+ if (argc > 0)
+ parse_lid_and_ports(h, argv[0], &lid, &position, &block);
+
+ memset(&mftr, 0, sizeof(mftr));
+ CHECK_AND_SET_VAL(lid, 16, 0, mftr.lid, MFTR, LID);
+ CHECK_AND_SET_VAL(block, 16, -1, mftr.position_block_num, MFTR, BLOCK);
+ mftr.position_block_num &= cl_hton16(IB_MCAST_BLOCK_ID_MASK_HO);
+ CHECK_AND_SET_VAL(position, 8, -1, pos, MFTR, POSITION);
+ mftr.position_block_num |= cl_hton16(pos << 12);
+
+ return get_and_dump_any_records(h, IB_SA_ATTR_MFTRECORD, 0, comp_mask,
+ &mftr, sizeof(mftr), dump_one_mft_record, p);
+}
+
+static int query_sa_cpi(struct sa_handle *h, struct query_params *query_params)
+{
+ ib_class_port_info_t *cpi;
+ struct sa_query_result result;
+ int ret = sa_query(h, IB_MAD_METHOD_GET, CLASS_PORT_INFO, 0, 0,
+ ibd_sakey, NULL, 0, &result);
+ if (ret) {
+ fprintf(stderr, "Query SA failed: %s\n", strerror(ret));
+ return ret;
+ }
+
+ if (result.status != IB_SA_MAD_STATUS_SUCCESS) {
+ sa_report_err(result.status);
+ ret = EIO;
+ goto Exit;
+ }
+ cpi = sa_get_query_rec(result.p_result_madw, 0);
+ memcpy(&query_params->cpi, cpi, sizeof(query_params->cpi));
+Exit:
+ sa_free_result_mad(&result);
+ return (0);
+}
+
+static const struct query_cmd query_cmds[] = {
+ {"ClassPortInfo", "CPI", CLASS_PORT_INFO,
+ NULL, query_class_port_info},
+ {"NodeRecord", "NR", IB_SA_ATTR_NODERECORD,
+ "[lid]", query_node_records},
+ {"PortInfoRecord", "PIR", IB_SA_ATTR_PORTINFORECORD,
+ "[[lid]/[port]/[options]]", query_portinfo_records},
+ {"SL2VLTableRecord", "SL2VL", IB_SA_ATTR_SL2VLTABLERECORD,
+ "[[lid]/[in_port]/[out_port]]", query_sl2vl_records},
+ {"PKeyTableRecord", "PKTR", IB_SA_ATTR_PKEYTABLERECORD,
+ "[[lid]/[port]/[block]]", query_pkey_tbl_records},
+ {"VLArbitrationTableRecord", "VLAR", IB_SA_ATTR_VLARBTABLERECORD,
+ "[[lid]/[port]/[block]]", query_vlarb_records},
+ {"InformInfoRecord", "IIR", IB_SA_ATTR_INFORMINFORECORD,
+ "[subscriber_gid]", query_inform_info_records},
+ {"LinkRecord", "LR", IB_SA_ATTR_LINKRECORD,
+ "[[from_lid]/[from_port]] [[to_lid]/[to_port]]", query_link_records},
+ {"ServiceRecord", "SR", IB_SA_ATTR_SERVICERECORD,
+ NULL, query_service_records},
+ {"PathRecord", "PR", IB_SA_ATTR_PATHRECORD,
+ NULL, query_path_records},
+ {"MCMemberRecord", "MCMR", IB_SA_ATTR_MCRECORD,
+ NULL, query_mcmember_records},
+ {"LFTRecord", "LFTR", IB_SA_ATTR_LFTRECORD,
+ "[[lid]/[block]]", query_lft_records},
+ {"MFTRecord", "MFTR", IB_SA_ATTR_MFTRECORD,
+ "[[mlid]/[position]/[block]]", query_mft_records},
+ {"GUIDInfoRecord", "GIR", IB_SA_ATTR_GUIDINFORECORD,
+ "[[lid]/[block]]", query_guidinfo_records},
+ {"SwitchInfoRecord", "SWIR", IB_SA_ATTR_SWITCHINFORECORD,
+ "[lid]", query_switchinfo_records},
+ {"SMInfoRecord", "SMIR", IB_SA_ATTR_SMINFORECORD,
+ "[lid]", query_sm_info_records},
+ {0}
+};
+
+static const struct query_cmd *find_query(const char *name)
+{
+ const struct query_cmd *q;
+
+ for (q = query_cmds; q->name; q++)
+ if (!strcasecmp(name, q->name) ||
+ (q->alias && !strcasecmp(name, q->alias)))
+ return q;
+
+ return NULL;
+}
+
+static const struct query_cmd *find_query_by_type(uint16_t type)
+{
+ const struct query_cmd *q;
+
+ for (q = query_cmds; q->name; q++)
+ if (q->query_type == type)
+ return q;
+
+ return NULL;
+}
+
+enum saquery_command {
+ SAQUERY_CMD_QUERY,
+ SAQUERY_CMD_NODE_RECORD,
+ SAQUERY_CMD_CLASS_PORT_INFO,
+ SAQUERY_CMD_ISSM,
+ SAQUERY_CMD_MCGROUPS,
+ SAQUERY_CMD_MCMEMBERS,
+};
+
+static enum saquery_command command = SAQUERY_CMD_QUERY;
+static uint16_t query_type;
+static char *src_lid, *dst_lid;
+
+static int process_opt(void *context, int ch, char *optarg)
+{
+ struct query_params *p = context;
+
+ switch (ch) {
+ case 1:
+ {
+ src_lid = strdup(optarg);
+ dst_lid = strchr(src_lid, ':');
+ if (!dst_lid)
+ ibdiag_show_usage();
+ *dst_lid++ = '\0';
+ }
+ p->numb_path = 0x7f;
+ query_type = IB_SA_ATTR_PATHRECORD;
+ break;
+ case 2:
+ {
+ char *src_addr = strdup(optarg);
+ char *dst_addr = strchr(src_addr, '-');
+ if (!dst_addr)
+ ibdiag_show_usage();
+ *dst_addr++ = '\0';
+ if (inet_pton(AF_INET6, src_addr, &p->sgid) <= 0)
+ ibdiag_show_usage();
+ if (inet_pton(AF_INET6, dst_addr, &p->dgid) <= 0)
+ ibdiag_show_usage();
+ free(src_addr);
+ }
+ p->numb_path = 0x7f;
+ query_type = IB_SA_ATTR_PATHRECORD;
+ break;
+ case 3:
+ node_name_map_file = strdup(optarg);
+ break;
+ case 4:
+ if (!isxdigit(*optarg) && !(optarg = getpass("SM_Key: "))) {
+ fprintf(stderr, "cannot get SM_Key\n");
+ ibdiag_show_usage();
+ }
+ ibd_sakey = strtoull(optarg, NULL, 0);
+ break;
+ case 'p':
+ query_type = IB_SA_ATTR_PATHRECORD;
+ break;
+ case 'D':
+ node_print_desc = ALL_DESC;
+ command = SAQUERY_CMD_NODE_RECORD;
+ break;
+ case 'c':
+ command = SAQUERY_CMD_CLASS_PORT_INFO;
+ break;
+ case 'S':
+ query_type = IB_SA_ATTR_SERVICERECORD;
+ break;
+ case 'I':
+ query_type = IB_SA_ATTR_INFORMINFORECORD;
+ break;
+ case 'N':
+ command = SAQUERY_CMD_NODE_RECORD;
+ break;
+ case 'L':
+ node_print_desc = LID_ONLY;
+ command = SAQUERY_CMD_NODE_RECORD;
+ break;
+ case 'l':
+ node_print_desc = UNIQUE_LID_ONLY;
+ command = SAQUERY_CMD_NODE_RECORD;
+ break;
+ case 'G':
+ node_print_desc = GUID_ONLY;
+ command = SAQUERY_CMD_NODE_RECORD;
+ break;
+ case 'O':
+ node_print_desc = NAME_OF_LID;
+ command = SAQUERY_CMD_NODE_RECORD;
+ break;
+ case 'U':
+ node_print_desc = NAME_OF_GUID;
+ command = SAQUERY_CMD_NODE_RECORD;
+ break;
+ case 's':
+ command = SAQUERY_CMD_ISSM;
+ break;
+ case 'g':
+ command = SAQUERY_CMD_MCGROUPS;
+ break;
+ case 'm':
+ command = SAQUERY_CMD_MCMEMBERS;
+ break;
+ case 'x':
+ query_type = IB_SA_ATTR_LINKRECORD;
+ break;
+ case 5:
+ p->slid = (uint16_t) strtoul(optarg, NULL, 0);
+ break;
+ case 6:
+ p->dlid = (uint16_t) strtoul(optarg, NULL, 0);
+ break;
+ case 7:
+ p->mlid = (uint16_t) strtoul(optarg, NULL, 0);
+ break;
+ case 14:
+ if (inet_pton(AF_INET6, optarg, &p->sgid) <= 0)
+ ibdiag_show_usage();
+ break;
+ case 15:
+ if (inet_pton(AF_INET6, optarg, &p->dgid) <= 0)
+ ibdiag_show_usage();
+ break;
+ case 16:
+ if (inet_pton(AF_INET6, optarg, &p->gid) <= 0)
+ ibdiag_show_usage();
+ break;
+ case 17:
+ if (inet_pton(AF_INET6, optarg, &p->mgid) <= 0)
+ ibdiag_show_usage();
+ break;
+ case 'r':
+ p->reversible = strtoul(optarg, NULL, 0);
+ break;
+ case 'n':
+ p->numb_path = strtoul(optarg, NULL, 0);
+ break;
+ case 18:
+ if (!isxdigit(*optarg) && !(optarg = getpass("P_Key: "))) {
+ fprintf(stderr, "cannot get P_Key\n");
+ ibdiag_show_usage();
+ }
+ p->pkey = (uint16_t) strtoul(optarg, NULL, 0);
+ break;
+ case 'Q':
+ p->qos_class = strtoul(optarg, NULL, 0);
+ break;
+ case 19:
+ p->sl = strtoul(optarg, NULL, 0);
+ break;
+ case 'M':
+ p->mtu = (uint8_t) strtoul(optarg, NULL, 0);
+ break;
+ case 'R':
+ p->rate = (uint8_t) strtoul(optarg, NULL, 0);
+ break;
+ case 20:
+ p->pkt_life = (uint8_t) strtoul(optarg, NULL, 0);
+ break;
+ case 'q':
+ if (!isxdigit(*optarg) && !(optarg = getpass("Q_Key: "))) {
+ fprintf(stderr, "cannot get Q_Key\n");
+ ibdiag_show_usage();
+ }
+ p->qkey = strtoul(optarg, NULL, 0);
+ break;
+ case 'T':
+ p->tclass = (uint8_t) strtoul(optarg, NULL, 0);
+ break;
+ case 'F':
+ p->flow_label = strtoul(optarg, NULL, 0);
+ break;
+ case 'H':
+ p->hop_limit = strtoul(optarg, NULL, 0);
+ break;
+ case 21:
+ p->scope = (uint8_t) strtoul(optarg, NULL, 0);
+ break;
+ case 'J':
+ p->join_state = (uint8_t) strtoul(optarg, NULL, 0);
+ break;
+ case 'X':
+ p->proxy_join = strtoul(optarg, NULL, 0);
+ break;
+ case 22:
+ p->service_id = strtoull(optarg, NULL, 0);
+ break;
+ case 23:
+ p->with_grh = TRUE;
+ break;
+ case 24:
+ p->with_grh = TRUE;
+ if (inet_pton(AF_INET6, optarg, &p->sa_dgid) <= 0)
+ ibdiag_show_usage();
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ ib_portid_t portid = { 0 };
+ int port = 0;
+ int sa_cpi_required = 0;
+ char usage_args[1024];
+ struct sa_handle * h;
+ struct query_params params;
+ const struct query_cmd *q;
+ int status;
+ int n;
+
+ const struct ibdiag_opt opts[] = {
+ {"p", 'p', 0, NULL, "get PathRecord info"},
+ {"N", 'N', 0, NULL, "get NodeRecord info"},
+ {"L", 'L', 0, NULL, "return the Lids of the name specified"},
+ {"l", 'l', 0, NULL,
+ "return the unique Lid of the name specified"},
+ {"G", 'G', 0, NULL, "return the Guids of the name specified"},
+ {"O", 'O', 0, NULL, "return name for the Lid specified"},
+ {"U", 'U', 0, NULL, "return name for the Guid specified"},
+ {"s", 's', 0, NULL, "return the PortInfoRecords with isSM or"
+ " isSMdisabled capability mask bit on"},
+ {"g", 'g', 0, NULL, "get multicast group info"},
+ {"m", 'm', 0, NULL, "get multicast member info (if multicast"
+ " group specified, list member GIDs only for group specified,"
+ " for example 'saquery -m 0xC000')"},
+ {"x", 'x', 0, NULL, "get LinkRecord info"},
+ {"c", 'c', 0, NULL, "get the SA's class port info"},
+ {"S", 'S', 0, NULL, "get ServiceRecord info"},
+ {"I", 'I', 0, NULL, "get InformInfoRecord (subscription) info"},
+ {"list", 'D', 0, NULL, "the node desc of the CA's"},
+ {"with-grh", 23, 0, NULL, "add GRH to path record query"},
+ {"sa-dgid", 24, 1, "<gid>",
+ "Set destination GID (in IPv6 format) in the GRH"},
+ {"src-to-dst", 1, 1, "<src:dst>", "get a PathRecord for"
+ " <src:dst> where src and dst are either node names or LIDs"},
+ {"sgid-to-dgid", 2, 1, "<sgid-dgid>", "get a PathRecord for"
+ " <sgid-dgid> where sgid and dgid are addresses in IPv6 format"},
+ {"node-name-map", 3, 1, "<file>",
+ "specify a node name map file"},
+ {"smkey", 4, 1, "<val>",
+ "SA SM_Key value for the query."
+ " If non-numeric value (like 'x') is specified then"
+ " saquery will prompt for a value. "
+ " Default (when not specified here or in ibdiag.conf) is to "
+ " use SM_Key == 0 (or \"untrusted\")"},
+ {"slid", 5, 1, "<lid>", "Source LID (PathRecord)"},
+ {"dlid", 6, 1, "<lid>", "Destination LID (PathRecord)"},
+ {"mlid", 7, 1, "<lid>", "Multicast LID (MCMemberRecord)"},
+ {"sgid", 14, 1, "<gid>",
+ "Source GID (IPv6 format) (PathRecord)"},
+ {"dgid", 15, 1, "<gid>",
+ "Destination GID (IPv6 format) (PathRecord)"},
+ {"gid", 16, 1, "<gid>", "Port GID (MCMemberRecord)"},
+ {"mgid", 17, 1, "<gid>", "Multicast GID (MCMemberRecord)"},
+ {"reversible", 'r', 1, NULL, "Reversible path (PathRecord)"},
+ {"numb_path", 'n', 1, NULL, "Number of paths (PathRecord)"},
+ {"pkey", 18, 1, NULL, "P_Key (PathRecord, MCMemberRecord)."
+ " If non-numeric value (like 'x') is specified then"
+ " saquery will prompt for a value"},
+ {"qos_class", 'Q', 1, NULL, "QoS Class (PathRecord)"},
+ {"sl", 19, 1, NULL,
+ "Service level (PathRecord, MCMemberRecord)"},
+ {"mtu", 'M', 1, NULL,
+ "MTU and selector (PathRecord, MCMemberRecord)"},
+ {"rate", 'R', 1, NULL,
+ "Rate and selector (PathRecord, MCMemberRecord)"},
+ {"pkt_lifetime", 20, 1, NULL,
+ "Packet lifetime and selector (PathRecord, MCMemberRecord)"},
+ {"qkey", 'q', 1, NULL, "Q_Key (MCMemberRecord)."
+ " If non-numeric value (like 'x') is specified then"
+ " saquery will prompt for a value"},
+ {"tclass", 'T', 1, NULL,
+ "Traffic Class (PathRecord, MCMemberRecord)"},
+ {"flow_label", 'F', 1, NULL,
+ "Flow Label (PathRecord, MCMemberRecord)"},
+ {"hop_limit", 'H', 1, NULL,
+ "Hop limit (PathRecord, MCMemberRecord)"},
+ {"scope", 21, 1, NULL, "Scope (MCMemberRecord)"},
+ {"join_state", 'J', 1, NULL, "Join state (MCMemberRecord)"},
+ {"proxy_join", 'X', 1, NULL, "Proxy join (MCMemberRecord)"},
+ {"service_id", 22, 1, NULL, "ServiceID (PathRecord)"},
+ {0}
+ };
+
+ memset(&params, 0, sizeof params);
+ params.hop_limit = 0;
+ params.reversible = -1;
+ params.numb_path = -1;
+ params.qos_class = -1;
+ params.sl = -1;
+ params.proxy_join = -1;
+
+ n = sprintf(usage_args, "[query-name] [<name> | <lid> | <guid>]\n"
+ "\nSupported query names (and aliases):\n");
+ for (q = query_cmds; q->name; q++) {
+ n += snprintf(usage_args + n, sizeof(usage_args) - n,
+ " %s (%s) %s\n", q->name,
+ q->alias ? q->alias : "",
+ q->usage ? q->usage : "");
+ if (n >= sizeof(usage_args))
+ exit(-1);
+ }
+ snprintf(usage_args + n, sizeof(usage_args) - n,
+ "\n Queries node records by default.");
+
+ q = NULL;
+ ibd_timeout = DEFAULT_SA_TIMEOUT_MS;
+
+ ibdiag_process_opts(argc, argv, &params, "DGLsy", opts, process_opt,
+ usage_args, NULL);
+
+ argc -= optind;
+ argv += optind;
+
+ if (!query_type && command == SAQUERY_CMD_QUERY) {
+ if (!argc || !(q = find_query(argv[0])))
+ query_type = IB_SA_ATTR_NODERECORD;
+ else {
+ query_type = q->query_type;
+ argc--;
+ argv++;
+ }
+ }
+
+ if (argc) {
+ if (node_print_desc == NAME_OF_LID) {
+ requested_lid = (uint16_t) strtoul(argv[0], NULL, 0);
+ requested_lid_flag++;
+ } else if (node_print_desc == NAME_OF_GUID) {
+ requested_guid = strtoul(argv[0], NULL, 0);
+ requested_guid_flag++;
+ } else
+ requested_name = argv[0];
+ }
+
+ if ((node_print_desc == LID_ONLY ||
+ node_print_desc == UNIQUE_LID_ONLY ||
+ node_print_desc == GUID_ONLY) && !requested_name) {
+ fprintf(stderr, "ERROR: name not specified\n");
+ ibdiag_show_usage();
+ }
+
+ if (node_print_desc == NAME_OF_LID && !requested_lid_flag) {
+ fprintf(stderr, "ERROR: lid not specified\n");
+ ibdiag_show_usage();
+ }
+
+ if (node_print_desc == NAME_OF_GUID && !requested_guid_flag) {
+ fprintf(stderr, "ERROR: guid not specified\n");
+ ibdiag_show_usage();
+ }
+
+ /* Note: lid cannot be 0; see infiniband spec 4.1.3 */
+ if (node_print_desc == NAME_OF_LID && !requested_lid) {
+ fprintf(stderr, "ERROR: lid invalid\n");
+ ibdiag_show_usage();
+ }
+
+ if (umad_init())
+ IBEXIT("Failed to initialized umad library");
+ h = sa_get_handle();
+ if (!h)
+ IBPANIC("Failed to bind to the SA");
+
+ if (params.with_grh) {
+ ibmad_gid_t gid = { 0 };
+ /*
+ * If GRH destination GID is not specified, try to get it by
+ * querying the SA.
+ */
+ if (!memcmp(&gid, &params.sa_dgid, sizeof(ibmad_gid_t))) {
+ if ((status = resolve_self(ibd_ca, ibd_ca_port, &portid,
+ &port, 0)) < 0) {
+ fprintf(stderr, "can't resolve self port %s\n",
+ argv[0]);
+ goto error;
+ }
+ if ((status = sm_pr_query(h, &gid, portid.lid,
+ h->dport.lid)) > 0) {
+ fprintf(stderr,
+ "Failed to query SA:PathRecord\n");
+ goto error;
+ }
+ } else
+ memcpy(&gid, &params.sa_dgid, sizeof(ibmad_gid_t));
+
+ if ((status = sa_set_handle(h, 1, &gid)) < 0) {
+ fprintf(stderr, "Failed to set GRH\n");
+ goto error;
+ }
+ }
+
+ node_name_map = open_node_name_map(node_name_map_file);
+
+ if (src_lid && *src_lid)
+ params.slid = get_lid(h, src_lid);
+ if (dst_lid && *dst_lid)
+ params.dlid = get_lid(h, dst_lid);
+
+ if (command == SAQUERY_CMD_CLASS_PORT_INFO ||
+ query_type == CLASS_PORT_INFO ||
+ query_type == IB_SA_ATTR_SWITCHINFORECORD)
+ sa_cpi_required = 1;
+
+ if (sa_cpi_required && (status = query_sa_cpi(h, &params)) != 0) {
+ fprintf(stderr, "Failed to query SA:ClassPortInfo\n");
+ goto error;
+ }
+
+ switch (command) {
+ case SAQUERY_CMD_NODE_RECORD:
+ status = print_node_records(h, &params);
+ break;
+ case SAQUERY_CMD_CLASS_PORT_INFO:
+ dump_class_port_info(&params.cpi);
+ status = 0;
+ break;
+ case SAQUERY_CMD_ISSM:
+ status = print_issm_records(h, &params);
+ break;
+ case SAQUERY_CMD_MCGROUPS:
+ status = print_multicast_group_records(h, &params);
+ break;
+ case SAQUERY_CMD_MCMEMBERS:
+ status = print_multicast_member_records(h, &params);
+ break;
+ default:
+ if ((!q && !(q = find_query_by_type(query_type)))
+ || !q->handler) {
+ fprintf(stderr, "Unknown query type %d\n",
+ ntohs(query_type));
+ status = EINVAL;
+ } else
+ status = q->handler(q, h, &params, argc, argv);
+ break;
+ }
+
+error:
+ if (src_lid)
+ free(src_lid);
+ sa_free_handle(h);
+ umad_done();
+ close_node_name_map(node_name_map);
+ return (status);
+}
diff --git a/contrib/ofed/infiniband-diags/src/sminfo.c b/contrib/ofed/infiniband-diags/src/sminfo.c
new file mode 100644
index 000000000000..894d9fc38262
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/src/sminfo.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2004-2009 Voltaire Inc. All rights reserved.
+ * Copyright (c) 2011 Mellanox Technologies LTD. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <getopt.h>
+
+#include <infiniband/umad.h>
+#include <infiniband/mad.h>
+
+#include "ibdiag_common.h"
+
+static uint8_t sminfo[1024] = { 0 };
+
+struct ibmad_port *srcport;
+
+int strdata, xdata = 1, bindata;
+
+enum {
+ SMINFO_NOTACT,
+ SMINFO_DISCOVER,
+ SMINFO_STANDBY,
+ SMINFO_MASTER,
+
+ SMINFO_STATE_LAST,
+};
+
+char *statestr[] = {
+ "SMINFO_NOTACT",
+ "SMINFO_DISCOVER",
+ "SMINFO_STANDBY",
+ "SMINFO_MASTER",
+};
+
+#define STATESTR(s) (((unsigned)(s)) < SMINFO_STATE_LAST ? statestr[s] : "???")
+
+static unsigned act;
+static int prio, state = SMINFO_STANDBY;
+
+static int process_opt(void *context, int ch, char *optarg)
+{
+ switch (ch) {
+ case 'a':
+ act = strtoul(optarg, 0, 0);
+ break;
+ case 's':
+ state = strtoul(optarg, 0, 0);
+ break;
+ case 'p':
+ prio = strtoul(optarg, 0, 0);
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ int mgmt_classes[3] =
+ { IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS };
+ int mod = 0;
+ ib_portid_t portid = { 0 };
+ uint8_t *p;
+ uint64_t guid = 0, key = 0;
+
+ const struct ibdiag_opt opts[] = {
+ {"state", 's', 1, "<0-3>", "set SM state"},
+ {"priority", 'p', 1, "<0-15>", "set SM priority"},
+ {"activity", 'a', 1, NULL, "set activity count"},
+ {0}
+ };
+ char usage_args[] = "<sm_lid|sm_dr_path> [modifier]";
+
+ ibdiag_process_opts(argc, argv, NULL, "sK", opts, process_opt,
+ usage_args, NULL);
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc > 1)
+ mod = atoi(argv[1]);
+
+ srcport = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 3);
+ if (!srcport)
+ IBEXIT("Failed to open '%s' port '%d'", ibd_ca, ibd_ca_port);
+
+ smp_mkey_set(srcport, ibd_mkey);
+
+ if (argc) {
+ if (resolve_portid_str(ibd_ca, ibd_ca_port, &portid, argv[0],
+ ibd_dest_type, 0, srcport) < 0)
+ IBEXIT("can't resolve destination port %s", argv[0]);
+ } else {
+ if (resolve_sm_portid(ibd_ca, ibd_ca_port, &portid) < 0)
+ IBEXIT("can't resolve sm port %s", argv[0]);
+ }
+
+ mad_encode_field(sminfo, IB_SMINFO_GUID_F, &guid);
+ mad_encode_field(sminfo, IB_SMINFO_ACT_F, &act);
+ mad_encode_field(sminfo, IB_SMINFO_KEY_F, &key);
+ mad_encode_field(sminfo, IB_SMINFO_PRIO_F, &prio);
+ mad_encode_field(sminfo, IB_SMINFO_STATE_F, &state);
+
+ if (mod) {
+ if (!(p = smp_set_via(sminfo, &portid, IB_ATTR_SMINFO, mod,
+ ibd_timeout, srcport)))
+ IBEXIT("query");
+ } else if (!(p = smp_query_via(sminfo, &portid, IB_ATTR_SMINFO, 0,
+ ibd_timeout, srcport)))
+ IBEXIT("query");
+
+ mad_decode_field(sminfo, IB_SMINFO_GUID_F, &guid);
+ mad_decode_field(sminfo, IB_SMINFO_ACT_F, &act);
+ mad_decode_field(sminfo, IB_SMINFO_KEY_F, &key);
+ mad_decode_field(sminfo, IB_SMINFO_PRIO_F, &prio);
+ mad_decode_field(sminfo, IB_SMINFO_STATE_F, &state);
+
+ printf("sminfo: sm lid %d sm guid 0x%" PRIx64
+ ", activity count %u priority %d state %d %s\n", portid.lid,
+ guid, act, prio, state, STATESTR(state));
+
+ mad_rpc_close_port(srcport);
+ exit(0);
+}
diff --git a/contrib/ofed/infiniband-diags/src/smpdump.c b/contrib/ofed/infiniband-diags/src/smpdump.c
new file mode 100644
index 000000000000..1c3776510d3b
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/src/smpdump.c
@@ -0,0 +1,318 @@
+/*
+ * Copyright (c) 2004-2009 Voltaire Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#define _GNU_SOURCE
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <inttypes.h>
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <netinet/in.h>
+
+#include <infiniband/mad.h>
+#include <infiniband/umad.h>
+
+#include <ibdiag_common.h>
+
+static int mad_agent;
+static int drmad_tid = 0x123;
+
+typedef struct {
+ char path[64];
+ int hop_cnt;
+} DRPath;
+
+struct drsmp {
+ uint8_t base_version;
+ uint8_t mgmt_class;
+ uint8_t class_version;
+ uint8_t method;
+ uint16_t status;
+ uint8_t hop_ptr;
+ uint8_t hop_cnt;
+ uint64_t tid;
+ uint16_t attr_id;
+ uint16_t resv;
+ uint32_t attr_mod;
+ uint64_t mkey;
+ uint16_t dr_slid;
+ uint16_t dr_dlid;
+ uint8_t reserved[28];
+ uint8_t data[64];
+ uint8_t initial_path[64];
+ uint8_t return_path[64];
+};
+
+void drsmp_get_init(void *umad, DRPath * path, int attr, int mod)
+{
+ struct drsmp *smp = (struct drsmp *)(umad_get_mad(umad));
+
+ memset(smp, 0, sizeof(*smp));
+
+ smp->base_version = 1;
+ smp->mgmt_class = IB_SMI_DIRECT_CLASS;
+ smp->class_version = 1;
+
+ smp->method = 1;
+ smp->attr_id = (uint16_t) htons((uint16_t) attr);
+ smp->attr_mod = htonl(mod);
+ smp->tid = htonll(drmad_tid++);
+ smp->dr_slid = 0xffff;
+ smp->dr_dlid = 0xffff;
+
+ umad_set_addr(umad, 0xffff, 0, 0, 0);
+
+ if (path)
+ memcpy(smp->initial_path, path->path, path->hop_cnt + 1);
+
+ smp->hop_cnt = (uint8_t) path->hop_cnt;
+}
+
+void smp_get_init(void *umad, int lid, int attr, int mod)
+{
+ struct drsmp *smp = (struct drsmp *)(umad_get_mad(umad));
+
+ memset(smp, 0, sizeof(*smp));
+
+ smp->base_version = 1;
+ smp->mgmt_class = IB_SMI_CLASS;
+ smp->class_version = 1;
+
+ smp->method = 1;
+ smp->attr_id = (uint16_t) htons((uint16_t) attr);
+ smp->attr_mod = htonl(mod);
+ smp->tid = htonll(drmad_tid++);
+
+ umad_set_addr(umad, lid, 0, 0, 0);
+}
+
+void drsmp_set_init(void *umad, DRPath * path, int attr, int mod, void *data)
+{
+ struct drsmp *smp = (struct drsmp *)(umad_get_mad(umad));
+
+ memset(smp, 0, sizeof(*smp));
+
+ smp->method = 2; /* SET */
+ smp->attr_id = (uint16_t) htons((uint16_t) attr);
+ smp->attr_mod = htonl(mod);
+ smp->tid = htonll(drmad_tid++);
+ smp->dr_slid = 0xffff;
+ smp->dr_dlid = 0xffff;
+
+ umad_set_addr(umad, 0xffff, 0, 0, 0);
+
+ if (path)
+ memcpy(smp->initial_path, path->path, path->hop_cnt + 1);
+
+ if (data)
+ memcpy(smp->data, data, sizeof smp->data);
+
+ smp->hop_cnt = (uint8_t) path->hop_cnt;
+}
+
+char *drmad_status_str(struct drsmp *drsmp)
+{
+ switch (drsmp->status) {
+ case 0:
+ return "success";
+ case ETIMEDOUT:
+ return "timeout";
+ }
+ return "unknown error";
+}
+
+int str2DRPath(char *str, DRPath * path)
+{
+ char *s;
+
+ path->hop_cnt = -1;
+
+ DEBUG("DR str: %s", str);
+ while (str && *str) {
+ if ((s = strchr(str, ',')))
+ *s = 0;
+ path->path[++path->hop_cnt] = (char)atoi(str);
+ if (!s)
+ break;
+ str = s + 1;
+ }
+
+#if 0
+ if (path->path[0] != 0 ||
+ (path->hop_cnt > 0 && dev_port && path->path[1] != dev_port)) {
+ DEBUG("hop 0 != 0 or hop 1 != dev_port");
+ return -1;
+ }
+#endif
+
+ return path->hop_cnt;
+}
+
+static int dump_char, mgmt_class = IB_SMI_CLASS;
+
+static int process_opt(void *context, int ch, char *optarg)
+{
+ switch (ch) {
+ case 's':
+ dump_char++;
+ break;
+ case 'D':
+ mgmt_class = IB_SMI_DIRECT_CLASS;
+ break;
+ case 'L':
+ mgmt_class = IB_SMI_CLASS;
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+#ifndef strdupa
+#define strdupa(_s) \
+({ \
+ char *_d; \
+ int _len; \
+ \
+ _len = strlen(_s) + 1; \
+ _d = alloca(_len); \
+ if (_d) \
+ memcpy(_d, _s, _len); \
+ _d; \
+})
+#endif
+
+int main(int argc, char *argv[])
+{
+ int dlid = 0;
+ void *umad;
+ struct drsmp *smp;
+ int i, portid, mod = 0, attr;
+ DRPath path;
+ uint8_t *desc;
+ int length;
+
+ const struct ibdiag_opt opts[] = {
+ {"string", 's', 0, NULL, ""},
+ {0}
+ };
+ char usage_args[] = "<dlid|dr_path> <attr> [mod]";
+ const char *usage_examples[] = {
+ " -- DR routed examples:",
+ "-D 0,1,2,3,5 16 # NODE DESC",
+ "-D 0,1,2 0x15 2 # PORT INFO, port 2",
+ " -- LID routed examples:",
+ "3 0x15 2 # PORT INFO, lid 3 port 2",
+ "0xa0 0x11 # NODE INFO, lid 0xa0",
+ NULL
+ };
+
+ ibd_timeout = 1000;
+
+ ibdiag_process_opts(argc, argv, NULL, "GKs", opts, process_opt,
+ usage_args, usage_examples);
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 2)
+ ibdiag_show_usage();
+
+ if (mgmt_class == IB_SMI_DIRECT_CLASS &&
+ str2DRPath(strdupa(argv[0]), &path) < 0)
+ IBPANIC("bad path str '%s'", argv[0]);
+
+ if (mgmt_class == IB_SMI_CLASS)
+ dlid = strtoul(argv[0], 0, 0);
+
+ attr = strtoul(argv[1], 0, 0);
+ if (argc > 2)
+ mod = strtoul(argv[2], 0, 0);
+
+ if (umad_init() < 0)
+ IBPANIC("can't init UMAD library");
+
+ if ((portid = umad_open_port(ibd_ca, ibd_ca_port)) < 0)
+ IBPANIC("can't open UMAD port (%s:%d)", ibd_ca, ibd_ca_port);
+
+ if ((mad_agent = umad_register(portid, mgmt_class, 1, 0, 0)) < 0)
+ IBPANIC("Couldn't register agent for SMPs");
+
+ if (!(umad = umad_alloc(1, umad_size() + IB_MAD_SIZE)))
+ IBPANIC("can't alloc MAD");
+
+ smp = umad_get_mad(umad);
+
+ if (mgmt_class == IB_SMI_DIRECT_CLASS)
+ drsmp_get_init(umad, &path, attr, mod);
+ else
+ smp_get_init(umad, dlid, attr, mod);
+
+ if (ibdebug > 1)
+ xdump(stderr, "before send:\n", smp, 256);
+
+ length = IB_MAD_SIZE;
+ if (umad_send(portid, mad_agent, umad, length, ibd_timeout, 0) < 0)
+ IBPANIC("send failed");
+
+ if (umad_recv(portid, umad, &length, -1) != mad_agent)
+ IBPANIC("recv error: %s", drmad_status_str(smp));
+
+ if (!dump_char) {
+ xdump(stdout, 0, smp->data, 64);
+ if (smp->status)
+ fprintf(stdout, "SMP status: 0x%x\n",
+ ntohs(smp->status));
+ goto exit;
+ }
+
+ desc = smp->data;
+ for (i = 0; i < 64; ++i) {
+ if (!desc[i])
+ break;
+ putchar(desc[i]);
+ }
+ putchar('\n');
+ if (smp->status)
+ fprintf(stdout, "SMP status: 0x%x\n", ntohs(smp->status));
+
+exit:
+ umad_free(umad);
+ return 0;
+}
diff --git a/contrib/ofed/infiniband-diags/src/smpquery.c b/contrib/ofed/infiniband-diags/src/smpquery.c
new file mode 100644
index 000000000000..2bd71320dc91
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/src/smpquery.c
@@ -0,0 +1,509 @@
+/*
+ * Copyright (c) 2004-2009 Voltaire Inc. All rights reserved.
+ * Copyright (c) 2011 Mellanox Technologies LTD. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <getopt.h>
+#include <netinet/in.h>
+
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
+
+#include <infiniband/umad.h>
+#include <infiniband/mad.h>
+#include <complib/cl_nodenamemap.h>
+
+#include "ibdiag_common.h"
+
+struct ibmad_port *srcport;
+
+static op_fn_t node_desc, node_info, port_info, switch_info, pkey_table,
+ sl2vl_table, vlarb_table, guid_info, mlnx_ext_port_info, port_info_extended;
+
+static const match_rec_t match_tbl[] = {
+ {"NodeInfo", "NI", node_info, 0, ""},
+ {"NodeDesc", "ND", node_desc, 0, ""},
+ {"PortInfo", "PI", port_info, 1, ""},
+ {"PortInfoExtended", "PIE", port_info_extended, 1, ""},
+ {"SwitchInfo", "SI", switch_info, 0, ""},
+ {"PKeyTable", "PKeys", pkey_table, 1, ""},
+ {"SL2VLTable", "SL2VL", sl2vl_table, 1, ""},
+ {"VLArbitration", "VLArb", vlarb_table, 1, ""},
+ {"GUIDInfo", "GI", guid_info, 0, ""},
+ {"MlnxExtPortInfo", "MEPI", mlnx_ext_port_info, 1, ""},
+ {0}
+};
+
+static char *node_name_map_file = NULL;
+static nn_map_t *node_name_map = NULL;
+static int extended_speeds = 0;
+
+/*******************************************/
+static char *node_desc(ib_portid_t * dest, char **argv, int argc)
+{
+ int node_type, l;
+ uint64_t node_guid;
+ char nd[IB_SMP_DATA_SIZE] = { 0 };
+ uint8_t data[IB_SMP_DATA_SIZE] = { 0 };
+ char dots[128];
+ char *nodename = NULL;
+
+ if (!smp_query_via(data, dest, IB_ATTR_NODE_INFO, 0, 0, srcport))
+ return "node info query failed";
+
+ mad_decode_field(data, IB_NODE_TYPE_F, &node_type);
+ mad_decode_field(data, IB_NODE_GUID_F, &node_guid);
+
+ if (!smp_query_via(nd, dest, IB_ATTR_NODE_DESC, 0, 0, srcport))
+ return "node desc query failed";
+
+ nodename = remap_node_name(node_name_map, node_guid, nd);
+
+ l = strlen(nodename);
+ if (l < 32) {
+ memset(dots, '.', 32 - l);
+ dots[32 - l] = '\0';
+ } else {
+ dots[0] = '.';
+ dots[1] = '\0';
+ }
+
+ printf("Node Description:%s%s\n", dots, nodename);
+ free(nodename);
+ return 0;
+}
+
+static char *node_info(ib_portid_t * dest, char **argv, int argc)
+{
+ char buf[2048];
+ char data[IB_SMP_DATA_SIZE] = { 0 };
+
+ if (!smp_query_via(data, dest, IB_ATTR_NODE_INFO, 0, 0, srcport))
+ return "node info query failed";
+
+ mad_dump_nodeinfo(buf, sizeof buf, data, sizeof data);
+
+ printf("# Node info: %s\n%s", portid2str(dest), buf);
+ return 0;
+}
+
+static char *port_info_extended(ib_portid_t * dest, char **argv, int argc)
+{
+ char buf[2048];
+ uint8_t data[IB_SMP_DATA_SIZE] = { 0 };
+ int portnum = 0;
+
+ if (argc > 0)
+ portnum = strtol(argv[0], 0, 0);
+
+ if (!is_port_info_extended_supported(dest, portnum, srcport))
+ return "port info extended not supported";
+
+ if (!smp_query_via(data, dest, IB_ATTR_PORT_INFO_EXT, portnum, 0,
+ srcport))
+ return "port info extended query failed";
+
+ mad_dump_portinfo_ext(buf, sizeof buf, data, sizeof data);
+ printf("# Port info Extended: %s port %d\n%s", portid2str(dest),
+ portnum, buf);
+ return 0;
+}
+
+static char *port_info(ib_portid_t * dest, char **argv, int argc)
+{
+ char data[IB_SMP_DATA_SIZE] = { 0 };
+ int portnum = 0, orig_portnum;
+
+ if (argc > 0)
+ portnum = strtol(argv[0], 0, 0);
+ orig_portnum = portnum;
+ if (extended_speeds)
+ portnum |= 1 << 31;
+
+ if (!smp_query_via(data, dest, IB_ATTR_PORT_INFO, portnum, 0, srcport))
+ return "port info query failed";
+
+ printf("# Port info: %s port %d\n", portid2str(dest), orig_portnum);
+ dump_portinfo(data, 0);
+ return 0;
+}
+
+static char *mlnx_ext_port_info(ib_portid_t * dest, char **argv, int argc)
+{
+ char buf[2300];
+ char data[IB_SMP_DATA_SIZE];
+ int portnum = 0;
+
+ if (argc > 0)
+ portnum = strtol(argv[0], 0, 0);
+
+ if (!smp_query_via(data, dest, IB_ATTR_MLNX_EXT_PORT_INFO, portnum, 0, srcport))
+ return "Mellanox ext port info query failed";
+
+ mad_dump_mlnx_ext_port_info(buf, sizeof buf, data, sizeof data);
+
+ printf("# MLNX ext Port info: %s port %d\n%s", portid2str(dest), portnum, buf);
+ return 0;
+}
+
+static char *switch_info(ib_portid_t * dest, char **argv, int argc)
+{
+ char buf[2048];
+ char data[IB_SMP_DATA_SIZE] = { 0 };
+
+ if (!smp_query_via(data, dest, IB_ATTR_SWITCH_INFO, 0, 0, srcport))
+ return "switch info query failed";
+
+ mad_dump_switchinfo(buf, sizeof buf, data, sizeof data);
+
+ printf("# Switch info: %s\n%s", portid2str(dest), buf);
+ return 0;
+}
+
+static char *pkey_table(ib_portid_t * dest, char **argv, int argc)
+{
+ uint8_t data[IB_SMP_DATA_SIZE] = { 0 };
+ int i, j, k;
+ uint16_t *p;
+ unsigned mod;
+ int n, t, phy_ports;
+ int portnum = 0;
+
+ if (argc > 0)
+ portnum = strtol(argv[0], 0, 0);
+
+ /* Get the partition capacity */
+ if (!smp_query_via(data, dest, IB_ATTR_NODE_INFO, 0, 0, srcport))
+ return "node info query failed";
+
+ mad_decode_field(data, IB_NODE_TYPE_F, &t);
+ mad_decode_field(data, IB_NODE_NPORTS_F, &phy_ports);
+ if (portnum > phy_ports)
+ return "invalid port number";
+
+ if ((t == IB_NODE_SWITCH) && (portnum != 0)) {
+ if (!smp_query_via(data, dest, IB_ATTR_SWITCH_INFO, 0, 0,
+ srcport))
+ return "switch info failed";
+ mad_decode_field(data, IB_SW_PARTITION_ENFORCE_CAP_F, &n);
+ } else
+ mad_decode_field(data, IB_NODE_PARTITION_CAP_F, &n);
+
+ for (i = 0; i < (n + 31) / 32; i++) {
+ mod = i | (portnum << 16);
+ if (!smp_query_via(data, dest, IB_ATTR_PKEY_TBL, mod, 0,
+ srcport))
+ return "pkey table query failed";
+ if (i + 1 == (n + 31) / 32)
+ k = ((n + 7 - i * 32) / 8) * 8;
+ else
+ k = 32;
+ p = (uint16_t *) data;
+ for (j = 0; j < k; j += 8, p += 8) {
+ printf
+ ("%4u: 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x 0x%04x\n",
+ (i * 32) + j, ntohs(p[0]), ntohs(p[1]),
+ ntohs(p[2]), ntohs(p[3]), ntohs(p[4]), ntohs(p[5]),
+ ntohs(p[6]), ntohs(p[7]));
+ }
+ }
+ printf("%d pkeys capacity for this port\n", n);
+
+ return 0;
+}
+
+static char *sl2vl_dump_table_entry(ib_portid_t * dest, int in, int out)
+{
+ char buf[2048];
+ char data[IB_SMP_DATA_SIZE] = { 0 };
+ int portnum = (in << 8) | out;
+
+ if (!smp_query_via(data, dest, IB_ATTR_SLVL_TABLE, portnum, 0, srcport))
+ return "slvl query failed";
+
+ mad_dump_sltovl(buf, sizeof buf, data, sizeof data);
+ printf("ports: in %2d, out %2d: ", in, out);
+ printf("%s", buf);
+ return 0;
+}
+
+static char *sl2vl_table(ib_portid_t * dest, char **argv, int argc)
+{
+ uint8_t data[IB_SMP_DATA_SIZE] = { 0 };
+ int type, num_ports, portnum = 0;
+ int i;
+ char *ret;
+
+ if (argc > 0)
+ portnum = strtol(argv[0], 0, 0);
+
+ if (!smp_query_via(data, dest, IB_ATTR_NODE_INFO, 0, 0, srcport))
+ return "node info query failed";
+
+ mad_decode_field(data, IB_NODE_TYPE_F, &type);
+ mad_decode_field(data, IB_NODE_NPORTS_F, &num_ports);
+ if (portnum > num_ports)
+ return "invalid port number";
+
+ printf("# SL2VL table: %s\n", portid2str(dest));
+ printf("# SL: |");
+ for (i = 0; i < 16; i++)
+ printf("%2d|", i);
+ printf("\n");
+
+ if (type != IB_NODE_SWITCH)
+ return sl2vl_dump_table_entry(dest, 0, 0);
+
+ for (i = 0; i <= num_ports; i++) {
+ ret = sl2vl_dump_table_entry(dest, i, portnum);
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+
+static char *vlarb_dump_table_entry(ib_portid_t * dest, int portnum, int offset,
+ unsigned cap)
+{
+ char buf[2048];
+ char data[IB_SMP_DATA_SIZE] = { 0 };
+
+ if (!smp_query_via(data, dest, IB_ATTR_VL_ARBITRATION,
+ (offset << 16) | portnum, 0, srcport))
+ return "vl arb query failed";
+ mad_dump_vlarbitration(buf, sizeof(buf), data, cap * 2);
+ printf("%s", buf);
+ return 0;
+}
+
+static char *vlarb_dump_table(ib_portid_t * dest, int portnum,
+ char *name, int offset, int cap)
+{
+ char *ret;
+
+ printf("# %s priority VL Arbitration Table:", name);
+ ret = vlarb_dump_table_entry(dest, portnum, offset,
+ cap < 32 ? cap : 32);
+ if (!ret && cap > 32)
+ ret = vlarb_dump_table_entry(dest, portnum, offset + 1,
+ cap - 32);
+ return ret;
+}
+
+static char *vlarb_table(ib_portid_t * dest, char **argv, int argc)
+{
+ uint8_t data[IB_SMP_DATA_SIZE] = { 0 };
+ int portnum = 0;
+ int type, enhsp0, lowcap, highcap;
+ char *ret = 0;
+
+ if (argc > 0)
+ portnum = strtol(argv[0], 0, 0);
+
+ /* port number of 0 could mean SP0 or port MAD arrives on */
+ if (portnum == 0) {
+ if (!smp_query_via(data, dest, IB_ATTR_NODE_INFO, 0, 0,
+ srcport))
+ return "node info query failed";
+
+ mad_decode_field(data, IB_NODE_TYPE_F, &type);
+ if (type == IB_NODE_SWITCH) {
+ memset(data, 0, sizeof(data));
+ if (!smp_query_via(data, dest, IB_ATTR_SWITCH_INFO, 0,
+ 0, srcport))
+ return "switch info query failed";
+ mad_decode_field(data, IB_SW_ENHANCED_PORT0_F, &enhsp0);
+ if (!enhsp0) {
+ printf
+ ("# No VLArbitration tables (BSP0): %s port %d\n",
+ portid2str(dest), 0);
+ return 0;
+ }
+ memset(data, 0, sizeof(data));
+ }
+ }
+
+ if (!smp_query_via(data, dest, IB_ATTR_PORT_INFO, portnum, 0, srcport))
+ return "port info query failed";
+
+ mad_decode_field(data, IB_PORT_VL_ARBITRATION_LOW_CAP_F, &lowcap);
+ mad_decode_field(data, IB_PORT_VL_ARBITRATION_HIGH_CAP_F, &highcap);
+
+ printf("# VLArbitration tables: %s port %d LowCap %d HighCap %d\n",
+ portid2str(dest), portnum, lowcap, highcap);
+
+ if (lowcap > 0)
+ ret = vlarb_dump_table(dest, portnum, "Low", 1, lowcap);
+
+ if (!ret && highcap > 0)
+ ret = vlarb_dump_table(dest, portnum, "High", 3, highcap);
+
+ return ret;
+}
+
+static char *guid_info(ib_portid_t * dest, char **argv, int argc)
+{
+ uint8_t data[IB_SMP_DATA_SIZE] = { 0 };
+ int i, j, k;
+ uint64_t *p;
+ unsigned mod;
+ int n;
+
+ /* Get the guid capacity */
+ if (!smp_query_via(data, dest, IB_ATTR_PORT_INFO, 0, 0, srcport))
+ return "port info failed";
+ mad_decode_field(data, IB_PORT_GUID_CAP_F, &n);
+
+ for (i = 0; i < (n + 7) / 8; i++) {
+ mod = i;
+ if (!smp_query_via(data, dest, IB_ATTR_GUID_INFO, mod, 0,
+ srcport))
+ return "guid info query failed";
+ if (i + 1 == (n + 7) / 8)
+ k = ((n + 1 - i * 8) / 2) * 2;
+ else
+ k = 8;
+ p = (uint64_t *) data;
+ for (j = 0; j < k; j += 2, p += 2) {
+ printf("%4u: 0x%016" PRIx64 " 0x%016" PRIx64 "\n",
+ (i * 8) + j, ntohll(p[0]), ntohll(p[1]));
+ }
+ }
+ printf("%d guids capacity for this port\n", n);
+
+ return 0;
+}
+
+static int process_opt(void *context, int ch, char *optarg)
+{
+ switch (ch) {
+ case 1:
+ node_name_map_file = strdup(optarg);
+ break;
+ case 'c':
+ ibd_dest_type = IB_DEST_DRSLID;
+ break;
+ case 'x':
+ extended_speeds = 1;
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ char usage_args[1024];
+ int mgmt_classes[3] =
+ { IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS };
+ ib_portid_t portid = { 0 };
+ char *err;
+ op_fn_t *fn;
+ const match_rec_t *r;
+ int n;
+
+ const struct ibdiag_opt opts[] = {
+ {"combined", 'c', 0, NULL,
+ "use Combined route address argument"},
+ {"node-name-map", 1, 1, "<file>", "node name map file"},
+ {"extended", 'x', 0, NULL, "use extended speeds"},
+ {0}
+ };
+ const char *usage_examples[] = {
+ "portinfo 3 1\t\t\t\t# portinfo by lid, with port modifier",
+ "-G switchinfo 0x2C9000100D051 1\t# switchinfo by guid",
+ "-D nodeinfo 0\t\t\t\t# nodeinfo by direct route",
+ "-c nodeinfo 6 0,12\t\t\t# nodeinfo by combined route",
+ NULL
+ };
+
+ n = sprintf(usage_args, "<op> <dest dr_path|lid|guid> [op params]\n"
+ "\nSupported ops (and aliases, case insensitive):\n");
+ for (r = match_tbl; r->name; r++) {
+ n += snprintf(usage_args + n, sizeof(usage_args) - n,
+ " %s (%s) <addr>%s\n", r->name,
+ r->alias ? r->alias : "",
+ r->opt_portnum ? " [<portnum>]" : "");
+ if (n >= sizeof(usage_args))
+ exit(-1);
+ }
+
+ ibdiag_process_opts(argc, argv, NULL, NULL, opts, process_opt,
+ usage_args, usage_examples);
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 2)
+ ibdiag_show_usage();
+
+ if (!(fn = match_op(match_tbl, argv[0])))
+ IBEXIT("operation '%s' not supported", argv[0]);
+
+ srcport = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 3);
+ if (!srcport)
+ IBEXIT("Failed to open '%s' port '%d'", ibd_ca, ibd_ca_port);
+
+ smp_mkey_set(srcport, ibd_mkey);
+
+ node_name_map = open_node_name_map(node_name_map_file);
+
+ if (ibd_dest_type != IB_DEST_DRSLID) {
+ if (resolve_portid_str(ibd_ca, ibd_ca_port, &portid, argv[1],
+ ibd_dest_type, ibd_sm_id, srcport) < 0)
+ IBEXIT("can't resolve destination port %s", argv[1]);
+ if ((err = fn(&portid, argv + 2, argc - 2)))
+ IBEXIT("operation %s: %s", argv[0], err);
+ } else {
+ char concat[64];
+
+ memset(concat, 0, 64);
+ snprintf(concat, sizeof(concat), "%s %s", argv[1], argv[2]);
+ if (resolve_portid_str(ibd_ca, ibd_ca_port, &portid, concat,
+ ibd_dest_type, ibd_sm_id, srcport) < 0)
+ IBEXIT("can't resolve destination port %s", concat);
+ if ((err = fn(&portid, argv + 3, argc - 3)))
+ IBEXIT("operation %s: %s", argv[0], err);
+ }
+ close_node_name_map(node_name_map);
+ mad_rpc_close_port(srcport);
+ exit(0);
+}
diff --git a/contrib/ofed/infiniband-diags/src/vendstat.c b/contrib/ofed/infiniband-diags/src/vendstat.c
new file mode 100644
index 000000000000..9cef1043c599
--- /dev/null
+++ b/contrib/ofed/infiniband-diags/src/vendstat.c
@@ -0,0 +1,552 @@
+/*
+ * Copyright (c) 2012 Mellanox Technologies LTD. All rights reserved.
+ * Copyright (c) 2004-2009 Voltaire Inc. All rights reserved.
+ *
+ * This software is available to you under a choice of one of two
+ * licenses. You may choose to be licensed under the terms of the GNU
+ * General Public License (GPL) Version 2, available from the file
+ * COPYING in the main directory of this source tree, or the
+ * OpenIB.org BSD license below:
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials
+ * provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <netinet/in.h>
+
+#include <infiniband/umad.h>
+#include <infiniband/mad.h>
+
+#include "ibdiag_common.h"
+
+#define IS3_DEVICE_ID 47396
+
+#define IB_MLX_VENDOR_CLASS 10
+/* Vendor specific Attribute IDs */
+#define IB_MLX_IS3_GENERAL_INFO 0x17
+#define IB_MLX_IS3_CONFIG_SPACE_ACCESS 0x50
+#define IB_MLX_IS4_COUNTER_GROUP_INFO 0x90
+#define IB_MLX_IS4_CONFIG_COUNTER_GROUP 0x91
+/* Config space addresses */
+#define IB_MLX_IS3_PORT_XMIT_WAIT 0x10013C
+
+
+struct ibmad_port *srcport;
+
+static ibmad_gid_t dgid;
+static int with_grh;
+
+typedef struct {
+ uint16_t hw_revision;
+ uint16_t device_id;
+ uint8_t reserved[24];
+ uint32_t uptime;
+} is3_hw_info_t;
+
+typedef struct {
+ uint8_t resv1;
+ uint8_t major;
+ uint8_t minor;
+ uint8_t sub_minor;
+ uint32_t build_id;
+ uint8_t month;
+ uint8_t day;
+ uint16_t year;
+ uint16_t resv2;
+ uint16_t hour;
+ uint8_t psid[16];
+ uint32_t ini_file_version;
+} is3_fw_info_t;
+
+typedef struct {
+ uint32_t ext_major;
+ uint32_t ext_minor;
+ uint32_t ext_sub_minor;
+ uint32_t reserved[4];
+} is4_fw_ext_info_t;
+
+typedef struct {
+ uint8_t resv1;
+ uint8_t major;
+ uint8_t minor;
+ uint8_t sub_minor;
+ uint8_t resv2[28];
+} is3_sw_info_t;
+
+typedef struct {
+ uint8_t reserved[8];
+ is3_hw_info_t hw_info;
+ is3_fw_info_t fw_info;
+ is3_sw_info_t sw_info;
+} is3_general_info_t;
+
+typedef struct {
+ uint8_t reserved[8];
+ is3_hw_info_t hw_info;
+ is3_fw_info_t fw_info;
+ is4_fw_ext_info_t ext_fw_info;
+ is3_sw_info_t sw_info;
+} is4_general_info_t;
+
+typedef struct {
+ uint8_t reserved[8];
+ struct is3_record {
+ uint32_t address;
+ uint32_t data;
+ uint32_t mask;
+ } record[18];
+} is3_config_space_t;
+
+#define COUNTER_GROUPS_NUM 2
+
+typedef struct {
+ uint8_t reserved1[8];
+ uint8_t reserved[3];
+ uint8_t num_of_counter_groups;
+ uint32_t group_masks[COUNTER_GROUPS_NUM];
+} is4_counter_group_info_t;
+
+typedef struct {
+ uint8_t reserved[3];
+ uint8_t group_select;
+} is4_group_select_t;
+
+typedef struct {
+ uint8_t reserved1[8];
+ uint8_t reserved[4];
+ is4_group_select_t group_selects[COUNTER_GROUPS_NUM];
+} is4_config_counter_groups_t;
+
+static uint16_t ext_fw_info_device[][2] = {
+ {0x0245, 0x0245}, /* Switch-X */
+ {0xc738, 0xc73b}, /* Switch-X */
+ {0xcb20, 0xcb20}, /* Switch-IB */
+ {0xcf08, 0xcf08}, /* Switch-IB2*/
+ {0x01b3, 0x01b3}, /* IS-4 */
+ {0x1003, 0x1017}, /* Connect-X */
+ {0x1b02, 0x1b02}, /* Bull SwitchX */
+ {0x1b50, 0x1b50}, /* Bull SwitchX */
+ {0x1ba0, 0x1ba0}, /* Bull SwitchIB */
+ {0x1bd0, 0x1bd5}, /* Bull SwitchIB and SwitchIB2 */
+ {0x1b33, 0x1b33}, /* Bull ConnectX3 */
+ {0x1b73, 0x1b73}, /* Bull ConnectX3 */
+ {0x1b40, 0x1b41}, /* Bull ConnectX3 */
+ {0x1b60, 0x1b61}, /* Bull ConnectX3 */
+ {0x1b83, 0x1b83}, /* Bull ConnectIB */
+ {0x1b93, 0x1b94}, /* Bull ConnectIB */
+ {0x1bb4, 0x1bb5}, /* Bull ConnectX4 */
+ {0x1bc4, 0x1bc4}, /* Bull ConnectX4 */
+ {0x0000, 0x0000}};
+
+static int is_ext_fw_info_supported(uint16_t device_id) {
+ int i;
+ for (i = 0; ext_fw_info_device[i][0]; i++)
+ if (ext_fw_info_device[i][0] <= device_id &&
+ device_id <= ext_fw_info_device[i][1])
+ return 1;
+ return 0;
+}
+
+static int do_vendor(ib_portid_t *portid, struct ibmad_port *srcport,
+ uint8_t class, uint8_t method, uint16_t attr_id,
+ uint32_t attr_mod, void *data)
+{
+ ib_vendor_call_t call;
+
+ memset(&call, 0, sizeof(call));
+ call.mgmt_class = class;
+ call.method = method;
+ call.timeout = ibd_timeout;
+ call.attrid = attr_id;
+ call.mod = attr_mod;
+
+ if (!ib_vendor_call_via(data, portid, &call, srcport)) {
+ fprintf(stderr,"vendstat: method %u, attribute %u failure\n", method, attr_id);
+ return -1;
+ }
+ return 0;
+}
+
+static int do_config_space_records(ib_portid_t *portid, unsigned set,
+ is3_config_space_t *cs, unsigned records)
+{
+ unsigned i;
+
+ if (records > 18)
+ records = 18;
+ for (i = 0; i < records; i++) {
+ cs->record[i].address = htonl(cs->record[i].address);
+ cs->record[i].data = htonl(cs->record[i].data);
+ cs->record[i].mask = htonl(cs->record[i].mask);
+ }
+
+ if (do_vendor(portid, srcport, IB_MLX_VENDOR_CLASS,
+ set ? IB_MAD_METHOD_SET : IB_MAD_METHOD_GET,
+ IB_MLX_IS3_CONFIG_SPACE_ACCESS, 2 << 22 | records << 16,
+ cs)) {
+ fprintf(stderr,"cannot %s config space records\n", set ? "set" : "get");
+ return -1;
+ }
+ for (i = 0; i < records; i++) {
+ printf("Config space record at 0x%x: 0x%x\n",
+ ntohl(cs->record[i].address),
+ ntohl(cs->record[i].data & cs->record[i].mask));
+ }
+ return 0;
+}
+
+static int counter_groups_info(ib_portid_t * portid, int port)
+{
+ char buf[1024];
+ is4_counter_group_info_t *cg_info;
+ int i, num_cg;
+
+ /* Counter Group Info */
+ memset(&buf, 0, sizeof(buf));
+ if (do_vendor(portid, srcport, IB_MLX_VENDOR_CLASS, IB_MAD_METHOD_GET,
+ IB_MLX_IS4_COUNTER_GROUP_INFO, port, buf)) {
+ fprintf(stderr,"counter group info query failure\n");
+ return -1;
+ }
+ cg_info = (is4_counter_group_info_t *) & buf;
+ num_cg = cg_info->num_of_counter_groups;
+ printf("counter_group_info:\n");
+ printf("%d counter groups\n", num_cg);
+ for (i = 0; i < num_cg; i++)
+ printf("group%d mask %#x\n", i, ntohl(cg_info->group_masks[i]));
+ return 0;
+}
+
+/* Group0 counter config values */
+#define IS4_G0_PortXmtDataSL_0_7 0
+#define IS4_G0_PortXmtDataSL_8_15 1
+#define IS4_G0_PortRcvDataSL_0_7 2
+
+/* Group1 counter config values */
+#define IS4_G1_PortXmtDataSL_8_15 1
+#define IS4_G1_PortRcvDataSL_0_7 2
+#define IS4_G1_PortRcvDataSL_8_15 8
+
+static int cg0, cg1;
+
+static int config_counter_groups(ib_portid_t * portid, int port)
+{
+ char buf[1024];
+ is4_config_counter_groups_t *cg_config;
+
+ /* configure counter groups for groups 0 and 1 */
+ memset(&buf, 0, sizeof(buf));
+ cg_config = (is4_config_counter_groups_t *) & buf;
+
+ printf("counter_groups_config: configuring group0 %d group1 %d\n", cg0,
+ cg1);
+ cg_config->group_selects[0].group_select = (uint8_t) cg0;
+ cg_config->group_selects[1].group_select = (uint8_t) cg1;
+
+ if (do_vendor(portid, srcport, IB_MLX_VENDOR_CLASS, IB_MAD_METHOD_SET,
+ IB_MLX_IS4_CONFIG_COUNTER_GROUP, port, buf)) {
+ fprintf(stderr, "config counter group set failure\n");
+ return -1;
+ }
+ /* get config counter groups */
+ memset(&buf, 0, sizeof(buf));
+
+ if (do_vendor(portid, srcport, IB_MLX_VENDOR_CLASS, IB_MAD_METHOD_GET,
+ IB_MLX_IS4_CONFIG_COUNTER_GROUP, port, buf)) {
+ fprintf(stderr, "config counter group query failure\n");
+ return -1;
+ }
+ return 0;
+}
+
+static int general_info, xmit_wait, counter_group_info, config_counter_group;
+static is3_config_space_t write_cs, read_cs;
+static unsigned write_cs_records, read_cs_records;
+
+
+static int process_opt(void *context, int ch, char *optarg)
+{
+ int ret;
+ switch (ch) {
+ case 'N':
+ general_info = 1;
+ break;
+ case 'w':
+ xmit_wait = 1;
+ break;
+ case 'i':
+ counter_group_info = 1;
+ break;
+ case 'c':
+ config_counter_group = 1;
+ ret = sscanf(optarg, "%d,%d", &cg0, &cg1);
+ if (ret != 2)
+ return -1;
+ break;
+ case 'R':
+ if (read_cs_records >= 18)
+ break;
+ ret = sscanf(optarg, "%x,%x",
+ &read_cs.record[read_cs_records].address,
+ &read_cs.record[read_cs_records].mask);
+ if (ret < 1)
+ return -1;
+ else if (ret == 1)
+ read_cs.record[read_cs_records].mask = 0xffffffff;
+ read_cs_records++;
+ break;
+ case 'W':
+ if (write_cs_records >= 18)
+ break;
+ ret = sscanf(optarg, "%x,%x,%x",
+ &write_cs.record[write_cs_records].address,
+ &write_cs.record[write_cs_records].data,
+ &write_cs.record[write_cs_records].mask);
+ if (ret < 2)
+ return -1;
+ else if (ret == 2)
+ write_cs.record[write_cs_records].mask = 0xffffffff;
+ write_cs_records++;
+ break;
+ case 25:
+ if (!inet_pton(AF_INET6, optarg, &dgid)) {
+ fprintf(stderr, "dgid format is wrong!\n");
+ ibdiag_show_usage();
+ return 1;
+ }
+ with_grh = 1;
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ int mgmt_classes[2] = { IB_SA_CLASS, IB_MLX_VENDOR_CLASS };
+ ib_portid_t portid = { 0 };
+ int port = 0;
+ char buf[1024];
+ uint32_t fw_ver_major = 0;
+ uint32_t fw_ver_minor = 0;
+ uint32_t fw_ver_sub_minor = 0;
+ uint8_t sw_ver_major = 0, sw_ver_minor = 0, sw_ver_sub_minor = 0;
+ is3_general_info_t *gi_is3;
+ is4_general_info_t *gi_is4;
+ const struct ibdiag_opt opts[] = {
+ {"N", 'N', 0, NULL, "show IS3 or IS4 general information"},
+ {"w", 'w', 0, NULL, "show IS3 port xmit wait counters"},
+ {"i", 'i', 0, NULL, "show IS4 counter group info"},
+ {"c", 'c', 1, "<num,num>", "configure IS4 counter groups"},
+ {"Read", 'R', 1, "<addr,mask>", "Read configuration space record at addr"},
+ {"Write", 'W', 1, "<addr,val,mask>", "Write configuration space record at addr"},
+ {"dgid", 25, 1, NULL, "remote gid (IPv6 format)"},
+ {0}
+ };
+
+ char usage_args[] = "<lid|guid> [port]";
+ const char *usage_examples[] = {
+ "-N 6\t\t# read IS3 or IS4 general information",
+ "-w 6\t\t# read IS3 port xmit wait counters",
+ "-i 6 12\t# read IS4 port 12 counter group info",
+ "-c 0,1 6 12\t# configure IS4 port 12 counter groups for PortXmitDataSL",
+ "-c 2,8 6 12\t# configure IS4 port 12 counter groups for PortRcvDataSL",
+ NULL
+ };
+
+ ibdiag_process_opts(argc, argv, NULL, "DKy", opts, process_opt,
+ usage_args, usage_examples);
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc > 1)
+ port = strtoul(argv[1], 0, 0);
+
+ srcport = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 2);
+ if (!srcport)
+ IBEXIT("Failed to open '%s' port '%d'", ibd_ca, ibd_ca_port);
+
+ if (argc) {
+ if (with_grh && ibd_dest_type != IB_DEST_LID) {
+ mad_rpc_close_port(srcport);
+ IBEXIT("When using GRH, LID should be provided");
+ }
+ if (resolve_portid_str(ibd_ca, ibd_ca_port, &portid, argv[0],
+ ibd_dest_type, ibd_sm_id, srcport) < 0) {
+ mad_rpc_close_port(srcport);
+ IBEXIT("can't resolve destination port %s", argv[0]);
+ }
+ if (with_grh) {
+ portid.grh_present = 1;
+ memcpy(&portid.gid, &dgid, sizeof(portid.gid));
+ }
+ } else {
+ if (resolve_self(ibd_ca, ibd_ca_port, &portid, &port, 0) < 0) {
+ mad_rpc_close_port(srcport);
+ IBEXIT("can't resolve self port %s", argv[0]);
+ }
+ }
+
+ if (counter_group_info) {
+ counter_groups_info(&portid, port);
+ mad_rpc_close_port(srcport);
+ exit(0);
+ }
+
+ if (config_counter_group) {
+ config_counter_groups(&portid, port);
+ mad_rpc_close_port(srcport);
+ exit(0);
+ }
+
+ if (read_cs_records || write_cs_records) {
+ if (read_cs_records)
+ do_config_space_records(&portid, 0, &read_cs,
+ read_cs_records);
+ if (write_cs_records)
+ do_config_space_records(&portid, 1, &write_cs,
+ write_cs_records);
+ mad_rpc_close_port(srcport);
+ exit(0);
+ }
+
+ /* These are Mellanox specific vendor MADs */
+ /* but vendors change the VendorId so how know for sure ? */
+ /* Only General Info and Port Xmit Wait Counters */
+ /* queries are currently supported */
+ if (!general_info && !xmit_wait) {
+ mad_rpc_close_port(srcport);
+ IBEXIT("at least one of -N and -w must be specified");
+ }
+ /* Would need a list of these and it might not be complete */
+ /* so for right now, punt on this */
+
+ /* vendor ClassPortInfo is required attribute if class supported */
+ memset(&buf, 0, sizeof(buf));
+ if (do_vendor(&portid, srcport, IB_MLX_VENDOR_CLASS, IB_MAD_METHOD_GET,
+ CLASS_PORT_INFO, 0, buf)) {
+ mad_rpc_close_port(srcport);
+ IBEXIT("classportinfo query");
+ }
+ memset(&buf, 0, sizeof(buf));
+ gi_is3 = (is3_general_info_t *) &buf;
+ if (do_vendor(&portid, srcport, IB_MLX_VENDOR_CLASS, IB_MAD_METHOD_GET,
+ IB_MLX_IS3_GENERAL_INFO, 0, gi_is3)) {
+ mad_rpc_close_port(srcport);
+ IBEXIT("generalinfo query");
+ }
+
+ if (is_ext_fw_info_supported(ntohs(gi_is3->hw_info.device_id))) {
+ gi_is4 = (is4_general_info_t *) &buf;
+ fw_ver_major = ntohl(gi_is4->ext_fw_info.ext_major);
+ fw_ver_minor = ntohl(gi_is4->ext_fw_info.ext_minor);
+ fw_ver_sub_minor = ntohl(gi_is4->ext_fw_info.ext_sub_minor);
+ sw_ver_major = gi_is4->sw_info.major;
+ sw_ver_minor = gi_is4->sw_info.minor;
+ sw_ver_sub_minor = gi_is4->sw_info.sub_minor;
+ } else {
+ fw_ver_major = gi_is3->fw_info.major;
+ fw_ver_minor = gi_is3->fw_info.minor;
+ fw_ver_sub_minor = gi_is3->fw_info.sub_minor;
+ sw_ver_major = gi_is3->sw_info.major;
+ sw_ver_minor = gi_is3->sw_info.minor;
+ sw_ver_sub_minor = gi_is3->sw_info.sub_minor;
+ }
+
+ if (general_info) {
+ /* dump IS3 or IS4 general info here */
+ printf("hw_dev_rev: 0x%04x\n", ntohs(gi_is3->hw_info.hw_revision));
+ printf("hw_dev_id: 0x%04x\n", ntohs(gi_is3->hw_info.device_id));
+ printf("hw_uptime: 0x%08x\n", ntohl(gi_is3->hw_info.uptime));
+ printf("fw_version: %02d.%02d.%02d\n",
+ fw_ver_major, fw_ver_minor, fw_ver_sub_minor);
+ printf("fw_build_id: 0x%04x\n", ntohl(gi_is3->fw_info.build_id));
+ printf("fw_date: %02x/%02x/%04x\n",
+ gi_is3->fw_info.month, gi_is3->fw_info.day,
+ ntohs(gi_is3->fw_info.year));
+ printf("fw_psid: '%s'\n", gi_is3->fw_info.psid);
+ printf("fw_ini_ver: %d\n",
+ ntohl(gi_is3->fw_info.ini_file_version));
+ printf("sw_version: %02d.%02d.%02d\n", sw_ver_major,
+ sw_ver_minor, sw_ver_sub_minor);
+ }
+
+ if (xmit_wait) {
+ is3_config_space_t *cs;
+ unsigned i;
+
+ if (ntohs(gi_is3->hw_info.device_id) != IS3_DEVICE_ID) {
+ mad_rpc_close_port(srcport);
+ IBEXIT("Unsupported device ID 0x%x",
+ ntohs(gi_is3->hw_info.device_id));
+ }
+ memset(&buf, 0, sizeof(buf));
+ /* Set record addresses for each port */
+ cs = (is3_config_space_t *) & buf;
+ for (i = 0; i < 16; i++)
+ cs->record[i].address =
+ htonl(IB_MLX_IS3_PORT_XMIT_WAIT + ((i + 1) << 12));
+ if (do_vendor(&portid, srcport, IB_MLX_VENDOR_CLASS,
+ IB_MAD_METHOD_GET, IB_MLX_IS3_CONFIG_SPACE_ACCESS,
+ 2 << 22 | 16 << 16, cs)) {
+ mad_rpc_close_port(srcport);
+ IBEXIT("vendstat");
+ }
+ for (i = 0; i < 16; i++)
+ if (cs->record[i].data) /* PortXmitWait is 32 bit counter */
+ printf("Port %d: PortXmitWait 0x%x\n", i + 4, ntohl(cs->record[i].data)); /* port 4 is first port */
+
+ /* Last 8 ports is another query */
+ memset(&buf, 0, sizeof(buf));
+ /* Set record addresses for each port */
+ cs = (is3_config_space_t *) & buf;
+ for (i = 0; i < 8; i++)
+ cs->record[i].address =
+ htonl(IB_MLX_IS3_PORT_XMIT_WAIT + ((i + 17) << 12));
+ if (do_vendor(&portid, srcport, IB_MLX_VENDOR_CLASS,
+ IB_MAD_METHOD_GET, IB_MLX_IS3_CONFIG_SPACE_ACCESS,
+ 2 << 22 | 8 << 16, cs)) {
+ mad_rpc_close_port(srcport);
+ IBEXIT("vendstat");
+ }
+
+ for (i = 0; i < 8; i++)
+ if (cs->record[i].data) /* PortXmitWait is 32 bit counter */
+ printf("Port %d: PortXmitWait 0x%x\n",
+ i < 4 ? i + 21 : i - 3,
+ ntohl(cs->record[i].data));
+ }
+
+ mad_rpc_close_port(srcport);
+ exit(0);
+}