diff options
author | Hans Petter Selasky <hselasky@FreeBSD.org> | 2017-08-02 16:00:30 +0000 |
---|---|---|
committer | Hans Petter Selasky <hselasky@FreeBSD.org> | 2017-08-02 16:00:30 +0000 |
commit | d6b92ffa990dc57d8a969a98e3ca4e25ba39cbb2 (patch) | |
tree | 8cca73c0fa75739adf10581b9e68d682f63048f3 /contrib/ofed/infiniband-diags | |
parent | 434b6d2073f936acc361b1e343dd9615036e1cd9 (diff) | |
download | src-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')
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(¬ice, 0, sizeof(notice)); + build(¬ice, &selfportid); + + return mad_send_via(&trap_rpc, &sm_port, NULL, ¬ice, 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(¶ms, 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, ¶ms, "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, ¶ms.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, ¶ms.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, ¶ms)) != 0) { + fprintf(stderr, "Failed to query SA:ClassPortInfo\n"); + goto error; + } + + switch (command) { + case SAQUERY_CMD_NODE_RECORD: + status = print_node_records(h, ¶ms); + break; + case SAQUERY_CMD_CLASS_PORT_INFO: + dump_class_port_info(¶ms.cpi); + status = 0; + break; + case SAQUERY_CMD_ISSM: + status = print_issm_records(h, ¶ms); + break; + case SAQUERY_CMD_MCGROUPS: + status = print_multicast_group_records(h, ¶ms); + break; + case SAQUERY_CMD_MCMEMBERS: + status = print_multicast_member_records(h, ¶ms); + 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, ¶ms, 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); +} |