RoCE/infiniband upgrade to Linux v4.9 for kernel and userspace.

This commit merges projects/bsd_rdma_4_9 to head.

List of kernel sources used:
============================

1) kernel sources were cloned from git://github.com/torvalds/linux.git
Top commit 69973b830859bc6529a7a0468ba0d80ee5117826 - tag: v4.9, linux-4.9

2) krping was cloned from https://github.com/larrystevenwise/krping
Top commit 292a2f1abf0348285e678a82264740d52e4dcfe4

List of userspace 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.

NOTES:
======

1) The mthca driver has been removed in kernel and in userspace.
2) All GPLv2 only sources have been removed and where applicable
   rewritten from scratch under a BSD license.
3) List of fully supported drivers in userspace and kernel:
   a) iw_cxgbe (Chelsio)
   b) mlx4ib (Mellanox)
   c) mlx5ib (Mellanox)
4) WITH_OFED=YES is still required by make in order to build
   OFED userspace and kernel code.
5) Full support has been added for routable RoCE, RoCE v2.

Sponsored by:	Mellanox Technologies
This commit is contained in:
Hans Petter Selasky
2017-11-24 14:50:28 +00:00
1379 changed files with 169960 additions and 307533 deletions
+17 -9
View File
@@ -2410,16 +2410,24 @@ _lib_libradius= lib/libradius
.endif
.if ${MK_OFED} != "no"
_ofed_lib= contrib/ofed/usr.lib
_prebuild_libs+= contrib/ofed/usr.lib/libosmcomp
_prebuild_libs+= contrib/ofed/usr.lib/libopensm
_prebuild_libs+= contrib/ofed/usr.lib/libibcommon
_prebuild_libs+= contrib/ofed/usr.lib/libibverbs
_prebuild_libs+= contrib/ofed/usr.lib/libibumad
#
# The OFED libraries are built in four steps
# as reflected below, due to interdependencies.
#
# NOTE: Depending on contrib/ofed/include is only needed for
# the lib32 compat build.
#
_ofed_lib= \
contrib/ofed/include \
contrib/ofed/usr.lib/0 \
contrib/ofed/usr.lib/1 \
contrib/ofed/usr.lib/2 \
contrib/ofed/usr.lib/3
contrib/ofed/usr.lib/libopensm__L: lib/libthr__L
contrib/ofed/usr.lib/libosmcomp__L: lib/libthr__L
contrib/ofed/usr.lib/libibumad__L: contrib/ofed/usr.lib/libibcommon__L
contrib/ofed/usr.lib/0__L: contrib/ofed/include__L lib/libthr__L
contrib/ofed/usr.lib/1__L: contrib/ofed/usr.lib/0__L
contrib/ofed/usr.lib/2__L: contrib/ofed/usr.lib/1__L
contrib/ofed/usr.lib/3__L: contrib/ofed/usr.lib/2__L
.endif
.if ${MK_CASPER} != "no"
+8 -1
View File
@@ -1,3 +1,10 @@
SUBDIR = include usr.lib usr.bin
# $FreeBSD$
# NOTE: Make sure WITH_OFED=YES is set when building this top-level directory.
SUBDIR= \
include \
usr.lib \
usr.bin
.include <bsd.subdir.mk>
+189 -3
View File
@@ -1,5 +1,191 @@
.include <bsd.own.mk>
# $FreeBSD$
SUBDIR = infiniband rdma
IBVERBS= ${.CURDIR}/../libibverbs
IBMAD= ${.CURDIR}/../libibmad
IBUMAD= ${.CURDIR}/../libibumad
IBCM= ${.CURDIR}/../libibcm
IBND= ${.CURDIR}/../libibnetdisc
RDMACM= ${.CURDIR}/../librdmacm
RDMA= ${.CURDIR}/../../../sys/ofed/include/uapi/rdma
OSM= ${.CURDIR}/../opensm/include
.include <bsd.subdir.mk>
IBINCS= \
byteorder.h \
byteswap.h \
endian.h \
types.h \
udma_barrier.h \
${IBVERBS}/arch.h \
${IBVERBS}/driver.h \
${IBVERBS}/kern-abi.h \
${IBVERBS}/marshall.h \
${IBVERBS}/opcode.h \
${IBVERBS}/sa-kern-abi.h \
${IBVERBS}/sa.h \
${IBVERBS}/verbs.h \
${IBUMAD}/umad.h \
${IBUMAD}/umad_cm.h \
${IBUMAD}/umad_sa.h \
${IBUMAD}/umad_sm.h \
${IBUMAD}/umad_str.h \
${IBUMAD}/umad_types.h \
${IBMAD}/mad.h \
${IBMAD}/mad_osd.h \
${IBCM}/cm.h \
${IBCM}/cm_abi.h \
${IBND}/ibnetdisc.h \
${IBND}/ibnetdisc_osd.h \
${RDMACM}/ib.h
IBINCSDIR= ${INCLUDEDIR}/infiniband
RDMAINCS= \
${RDMACM}/rdma_cma.h \
${RDMACM}/rdma_cma_abi.h \
${RDMACM}/rdma_verbs.h \
${RDMACM}/rsocket.h \
${RDMA}/ib_user_cm.h \
${RDMA}/ib_user_sa.h \
${RDMA}/ib_user_verbs.h \
${RDMA}/rdma_user_cm.h \
${RDMA}/mlx4-abi.h \
${RDMA}/mlx5-abi.h
RDMAINCSDIR= ${INCLUDEDIR}/rdma
COMPINCS= \
${OSM}/complib/cl_atomic.h \
${OSM}/complib/cl_atomic_osd.h \
${OSM}/complib/cl_byteswap.h \
${OSM}/complib/cl_byteswap_osd.h \
${OSM}/complib/cl_comppool.h \
${OSM}/complib/cl_debug.h \
${OSM}/complib/cl_debug_osd.h \
${OSM}/complib/cl_dispatcher.h \
${OSM}/complib/cl_event.h \
${OSM}/complib/cl_event_osd.h \
${OSM}/complib/cl_event_wheel.h \
${OSM}/complib/cl_fleximap.h \
${OSM}/complib/cl_list.h \
${OSM}/complib/cl_log.h \
${OSM}/complib/cl_map.h \
${OSM}/complib/cl_math.h \
${OSM}/complib/cl_nodenamemap.h \
${OSM}/complib/cl_packoff.h \
${OSM}/complib/cl_packon.h \
${OSM}/complib/cl_passivelock.h \
${OSM}/complib/cl_pool.h \
${OSM}/complib/cl_ptr_vector.h \
${OSM}/complib/cl_qcomppool.h \
${OSM}/complib/cl_qlist.h \
${OSM}/complib/cl_qmap.h \
${OSM}/complib/cl_qpool.h \
${OSM}/complib/cl_spinlock.h \
${OSM}/complib/cl_spinlock_osd.h \
${OSM}/complib/cl_thread.h \
${OSM}/complib/cl_thread_osd.h \
${OSM}/complib/cl_threadpool.h \
${OSM}/complib/cl_timer.h \
${OSM}/complib/cl_timer_osd.h \
${OSM}/complib/cl_types.h \
${OSM}/complib/cl_types_osd.h \
${OSM}/complib/cl_vector.h
COMPINCSDIR= ${INCLUDEDIR}/infiniband/complib
OSMINCS= \
${OSM}/opensm/osm_attrib_req.h \
${OSM}/opensm/osm_base.h \
${OSM}/opensm/osm_config.h \
${OSM}/opensm/osm_congestion_control.h \
${OSM}/opensm/osm_console.h \
${OSM}/opensm/osm_console_io.h \
${OSM}/opensm/osm_db.h \
${OSM}/opensm/osm_db_pack.h \
${OSM}/opensm/osm_errors.h \
${OSM}/opensm/osm_event_plugin.h \
${OSM}/opensm/osm_file_ids.h \
${OSM}/opensm/osm_guid.h \
${OSM}/opensm/osm_helper.h \
${OSM}/opensm/osm_inform.h \
${OSM}/opensm/osm_lid_mgr.h \
${OSM}/opensm/osm_log.h \
${OSM}/opensm/osm_mad_pool.h \
${OSM}/opensm/osm_madw.h \
${OSM}/opensm/osm_mcast_mgr.h \
${OSM}/opensm/osm_mcast_tbl.h \
${OSM}/opensm/osm_mcm_port.h \
${OSM}/opensm/osm_mesh.h \
${OSM}/opensm/osm_msgdef.h \
${OSM}/opensm/osm_mtree.h \
${OSM}/opensm/osm_multicast.h \
${OSM}/opensm/osm_node.h \
${OSM}/opensm/osm_opensm.h \
${OSM}/opensm/osm_partition.h \
${OSM}/opensm/osm_path.h \
${OSM}/opensm/osm_perfmgr.h \
${OSM}/opensm/osm_perfmgr_db.h \
${OSM}/opensm/osm_pkey.h \
${OSM}/opensm/osm_port.h \
${OSM}/opensm/osm_port_profile.h \
${OSM}/opensm/osm_prefix_route.h \
${OSM}/opensm/osm_qos_policy.h \
${OSM}/opensm/osm_remote_sm.h \
${OSM}/opensm/osm_router.h \
${OSM}/opensm/osm_sa.h \
${OSM}/opensm/osm_sa_mad_ctrl.h \
${OSM}/opensm/osm_service.h \
${OSM}/opensm/osm_sm.h \
${OSM}/opensm/osm_sm_mad_ctrl.h \
${OSM}/opensm/osm_stats.h \
${OSM}/opensm/osm_subnet.h \
${OSM}/opensm/osm_switch.h \
${OSM}/opensm/osm_ucast_cache.h \
${OSM}/opensm/osm_ucast_lash.h \
${OSM}/opensm/osm_ucast_mgr.h \
${OSM}/opensm/osm_version.h \
${OSM}/opensm/osm_vl15intf.h \
${OSM}/opensm/st.h
OSMINCSDIR= ${INCLUDEDIR}/infiniband/opensm
IBAINCS= \
${OSM}/iba/ib_cm_types.h \
${OSM}/iba/ib_types.h
IBAINCSDIR= ${INCLUDEDIR}/infiniband/iba
VENDORINCS= \
${OSM}/vendor/osm_mtl_bind.h \
${OSM}/vendor/osm_pkt_randomizer.h \
${OSM}/vendor/osm_ts_useraccess.h \
${OSM}/vendor/osm_umadt.h \
${OSM}/vendor/osm_vendor.h \
${OSM}/vendor/osm_vendor_al.h \
${OSM}/vendor/osm_vendor_api.h \
${OSM}/vendor/osm_vendor_ibumad.h \
${OSM}/vendor/osm_vendor_mlx.h \
${OSM}/vendor/osm_vendor_mlx_defs.h \
${OSM}/vendor/osm_vendor_mlx_dispatcher.h \
${OSM}/vendor/osm_vendor_mlx_hca.h \
${OSM}/vendor/osm_vendor_mlx_inout.h \
${OSM}/vendor/osm_vendor_mlx_rmpp_ctx.h \
${OSM}/vendor/osm_vendor_mlx_sar.h \
${OSM}/vendor/osm_vendor_mlx_sender.h \
${OSM}/vendor/osm_vendor_mlx_svc.h \
${OSM}/vendor/osm_vendor_mlx_transport.h \
${OSM}/vendor/osm_vendor_mlx_transport_anafa.h \
${OSM}/vendor/osm_vendor_mlx_txn.h \
${OSM}/vendor/osm_vendor_mtl.h \
${OSM}/vendor/osm_vendor_mtl_hca_guid.h \
${OSM}/vendor/osm_vendor_mtl_transaction_mgr.h \
${OSM}/vendor/osm_vendor_sa_api.h \
${OSM}/vendor/osm_vendor_test.h \
${OSM}/vendor/osm_vendor_ts.h \
${OSM}/vendor/osm_vendor_umadt.h
VENDORINCSDIR= ${INCLUDEDIR}/infiniband/vendor
INCSGROUPS= \
IBINCS \
RDMAINCS \
COMPINCS \
OSMINCS \
IBAINCS \
VENDORINCS
.include <bsd.prog.mk>
-107
View File
@@ -1,107 +0,0 @@
.include <bsd.own.mk>
INCS=
IBINCS= byteorder.h byteswap.h endian.h types.h
IBINCSDIR= ${INCLUDEDIR}/infiniband
IBVERBS= ${.CURDIR}/../../libibverbs/include/infiniband
VERBINCS= ${IBVERBS}/arch.h ${IBVERBS}/driver.h ${IBVERBS}/kern-abi.h
VERBINCS+= ${IBVERBS}/marshall.h ${IBVERBS}/opcode.h
VERBINCS+= ${IBVERBS}/sa-kern-abi.h ${IBVERBS}/sa.h ${IBVERBS}/verbs.h
VERBINCSDIR= ${INCLUDEDIR}/infiniband
IBCOMMON= ${.CURDIR}/../../management/libibcommon/include/infiniband
COMMONINCS= ${IBCOMMON}/common.h
COMMONINCSDIR= ${INCLUDEDIR}/infiniband
IBMAD= ${.CURDIR}/../../management/libibmad/include/infiniband
MADINCS= ${IBMAD}/mad.h
MADINCSDIR= ${INCLUDEDIR}/infiniband
IBUMAD= ${.CURDIR}/../../management/libibumad/include/infiniband
UMADINCS= ${IBUMAD}/umad.h
UMADINCSDIR= ${INCLUDEDIR}/infiniband
COMPLIB= ${.CURDIR}/../../management/opensm/include/complib
COMPLIBINCS= ${COMPLIB}/cl_atomic.h ${COMPLIB}/cl_atomic_osd.h
COMPLIBINCS+= ${COMPLIB}/cl_byteswap.h ${COMPLIB}/cl_byteswap_osd.h
COMPLIBINCS+= ${COMPLIB}/cl_comppool.h ${COMPLIB}/cl_debug.h
COMPLIBINCS+= ${COMPLIB}/cl_debug_osd.h ${COMPLIB}/cl_dispatcher.h
COMPLIBINCS+= ${COMPLIB}/cl_event.h ${COMPLIB}/cl_event_osd.h
COMPLIBINCS+= ${COMPLIB}/cl_event_wheel.h ${COMPLIB}/cl_fleximap.h
COMPLIBINCS+= ${COMPLIB}/cl_list.h ${COMPLIB}/cl_log.h
COMPLIBINCS+= ${COMPLIB}/cl_map.h ${COMPLIB}/cl_math.h
COMPLIBINCS+= ${COMPLIB}/cl_nodenamemap.h ${COMPLIB}/cl_packoff.h
COMPLIBINCS+= ${COMPLIB}/cl_packon.h ${COMPLIB}/cl_passivelock.h
COMPLIBINCS+= ${COMPLIB}/cl_pool.h ${COMPLIB}/cl_ptr_vector.h
COMPLIBINCS+= ${COMPLIB}/cl_qcomppool.h ${COMPLIB}/cl_qlist.h
COMPLIBINCS+= ${COMPLIB}/cl_qmap.h ${COMPLIB}/cl_qpool.h
COMPLIBINCS+= ${COMPLIB}/cl_spinlock.h ${COMPLIB}/cl_spinlock_osd.h
COMPLIBINCS+= ${COMPLIB}/cl_thread.h ${COMPLIB}/cl_thread_osd.h
COMPLIBINCS+= ${COMPLIB}/cl_threadpool.h ${COMPLIB}/cl_timer.h
COMPLIBINCS+= ${COMPLIB}/cl_timer_osd.h ${COMPLIB}/cl_types.h
COMPLIBINCS+= ${COMPLIB}/cl_types_osd.h ${COMPLIB}/cl_vector.h
COMPLIBINCSDIR= ${INCLUDEDIR}/infiniband/complib
IBADIR= ${.CURDIR}/../../management/opensm/include/iba
IBAINCS= ${IBADIR}/ib_cm_types.h ${IBADIR}/ib_types.h
IBAINCSDIR= ${INCLUDEDIR}/infiniband/iba
OPENSM= ${.CURDIR}/../../management/opensm/include/opensm
OPENSMINCS= ${OPENSM}/osm_attrib_req.h ${OPENSM}/osm_base.h
OPENSMINCS+= ${OPENSM}/osm_config.h ${OPENSM}/osm_console.h
OPENSMINCS+= ${OPENSM}/osm_console_io.h ${OPENSM}/osm_db.h
OPENSMINCS+= ${OPENSM}/osm_db_pack.h ${OPENSM}/osm_errors.h
OPENSMINCS+= ${OPENSM}/osm_event_plugin.h ${OPENSM}/osm_helper.h
OPENSMINCS+= ${OPENSM}/osm_inform.h ${OPENSM}/osm_lid_mgr.h
OPENSMINCS+= ${OPENSM}/osm_log.h ${OPENSM}/osm_mad_pool.h
OPENSMINCS+= ${OPENSM}/osm_madw.h ${OPENSM}/osm_mcast_tbl.h
OPENSMINCS+= ${OPENSM}/osm_mcm_info.h ${OPENSM}/osm_mcm_port.h
OPENSMINCS+= ${OPENSM}/osm_msgdef.h ${OPENSM}/osm_mtree.h
OPENSMINCS+= ${OPENSM}/osm_multicast.h ${OPENSM}/osm_node.h
OPENSMINCS+= ${OPENSM}/osm_opensm.h ${OPENSM}/osm_partition.h
OPENSMINCS+= ${OPENSM}/osm_path.h ${OPENSM}/osm_perfmgr.h
OPENSMINCS+= ${OPENSM}/osm_perfmgr_db.h ${OPENSM}/osm_pkey.h
OPENSMINCS+= ${OPENSM}/osm_pkey_mgr.h ${OPENSM}/osm_port.h
OPENSMINCS+= ${OPENSM}/osm_port_profile.h ${OPENSM}/osm_prefix_route.h
OPENSMINCS+= ${OPENSM}/osm_qos_policy.h ${OPENSM}/osm_remote_sm.h
OPENSMINCS+= ${OPENSM}/osm_router.h ${OPENSM}/osm_sa.h
OPENSMINCS+= ${OPENSM}/osm_sa_mad_ctrl.h ${OPENSM}/osm_service.h
OPENSMINCS+= ${OPENSM}/osm_sm.h ${OPENSM}/osm_sm_mad_ctrl.h
OPENSMINCS+= ${OPENSM}/osm_stats.h ${OPENSM}/osm_subnet.h
OPENSMINCS+= ${OPENSM}/osm_switch.h ${OPENSM}/osm_ucast_cache.h
OPENSMINCS+= ${OPENSM}/osm_ucast_mgr.h ${OPENSM}/osm_version.h
OPENSMINCS+= ${OPENSM}/osm_vl15intf.h ${OPENSM}/st.h
OPENSMINCSDIR= ${INCLUDEDIR}/infiniband/opensm
VENDOR= ${.CURDIR}/../../management/opensm/include/vendor
VENDORINCS= ${VENDOR}/osm_mtl_bind.h ${VENDOR}/osm_pkt_randomizer.h
VENDORINCS+= ${VENDOR}/osm_ts_useraccess.h ${VENDOR}/osm_umadt.h
VENDORINCS+= ${VENDOR}/osm_vendor.h ${VENDOR}/osm_vendor_al.h
VENDORINCS+= ${VENDOR}/osm_vendor_api.h ${VENDOR}/osm_vendor_ibumad.h
VENDORINCS+= ${VENDOR}/osm_vendor_mlx.h ${VENDOR}/osm_vendor_mlx_defs.h
VENDORINCS+= ${VENDOR}/osm_vendor_mlx_dispatcher.h
VENDORINCS+= ${VENDOR}/osm_vendor_mlx_hca.h
VENDORINCS+= ${VENDOR}/osm_vendor_mlx_inout.h
VENDORINCS+= ${VENDOR}/osm_vendor_mlx_rmpp_ctx.h
VENDORINCS+= ${VENDOR}/osm_vendor_mlx_sar.h ${VENDOR}/osm_vendor_mlx_sender.h
VENDORINCS+= ${VENDOR}/osm_vendor_mlx_svc.h
VENDORINCS+= ${VENDOR}/osm_vendor_mlx_transport.h
VENDORINCS+= ${VENDOR}/osm_vendor_mlx_transport_anafa.h
VENDORINCS+= ${VENDOR}/osm_vendor_mlx_txn.h
VENDORINCS+= ${VENDOR}/osm_vendor_mtl.h ${VENDOR}/osm_vendor_mtl_hca_guid.h
VENDORINCS+= ${VENDOR}/osm_vendor_mtl_transaction_mgr.h
VENDORINCS+= ${VENDOR}/osm_vendor_sa_api.h
VENDORINCS+= ${VENDOR}/osm_vendor_test.h ${VENDOR}/osm_vendor_ts.h
VENDORINCS+= ${VENDOR}/osm_vendor_umadt.h
VENDORINCSDIR= ${INCLUDEDIR}/infiniband/vendor
IBCM= ${.CURDIR}/../../libibcm/include/infiniband
IBCMINCS= ${IBCM}/cm.h ${IBCM}/cm_abi.h
IBCMINCSDIR= ${INCLUDEDIR}/infiniband
INCSGROUPS= INCS VERBINCS COMMONINCS MADINCS UMADINCS COMPLIBINCS IBAINCS
INCSGROUPS+= OPENSMINCS VENDORINCS IBCMINCS IBINCS
.include <bsd.prog.mk>
-10
View File
@@ -1,10 +0,0 @@
.include <bsd.own.mk>
INCS=
RDMACM= ${.CURDIR}/../../librdmacm/include/rdma
RDMACMINCS= ${RDMACM}/rdma_cma.h ${RDMACM}/rdma_cma_abi.h
RDMACMINCSDIR= ${INCLUDEDIR}/rdma
INCSGROUPS= RDMACMINCS
.include <bsd.prog.mk>
@@ -58,6 +58,4 @@ typedef uint32_t __be32;
typedef uint64_t __le64;
typedef uint64_t __be64;
typedef unsigned int uint;
#endif /* _INFINIBAND_TYPES_H_ */
+261
View File
@@ -0,0 +1,261 @@
/*
* Copyright (c) 2005 Topspin Communications. 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 __UTIL_UDMA_BARRIER_H
#define __UTIL_UDMA_BARRIER_H
#include <pthread.h>
/* Barriers for DMA.
These barriers are expliclty only for use with user DMA operations. If you
are looking for barriers to use with cache-coherent multi-threaded
consitency then look in stdatomic.h. If you need both kinds of synchronicity
for the same address then use an atomic operation followed by one
of these barriers.
When reasoning about these barriers there are two objects:
- CPU attached address space (the CPU memory could be a range of things:
cached/uncached/non-temporal CPU DRAM, uncached MMIO space in another
device, pMEM). Generally speaking the ordering is only relative
to the local CPU's view of the system. Eg if the local CPU
is not guaranteed to see a write from another CPU then it is also
OK for the DMA device to also not see the write after the barrier.
- A DMA initiator on a bus. For instance a PCI-E device issuing
MemRd/MemWr TLPs.
The ordering guarantee is always stated between those two streams. Eg what
happens if a MemRd TLP is sent in via PCI-E relative to a CPU WRITE to the
same memory location.
The providers have a very regular and predictable use of these barriers,
to make things very clear each narrow use is given a name and the proper
name should be used in the provider as a form of documentation.
*/
/* Ensure that the device's view of memory matches the CPU's view of memory.
This should be placed before any MMIO store that could trigger the device
to begin doing DMA, such as a device doorbell ring.
eg
*dma_buf = 1;
udma_to_device_barrier();
mmio_write(DO_DMA_REG, dma_buf);
Must ensure that the device sees the '1'.
This is required to fence writes created by the libibverbs user. Those
writes could be to any CPU mapped memory object with any cachability mode.
NOTE: x86 has historically used a weaker semantic for this barrier, and
only fenced normal stores to normal memory. libibverbs users using other
memory types or non-temporal stores are required to use SFENCE in their own
code prior to calling verbs to start a DMA.
*/
#if defined(__i386__)
#define udma_to_device_barrier() asm volatile("" ::: "memory")
#elif defined(__x86_64__)
#define udma_to_device_barrier() asm volatile("" ::: "memory")
#elif defined(__PPC64__)
#define udma_to_device_barrier() asm volatile("sync" ::: "memory")
#elif defined(__PPC__)
#define udma_to_device_barrier() asm volatile("sync" ::: "memory")
#elif defined(__ia64__)
#define udma_to_device_barrier() asm volatile("mf" ::: "memory")
#elif defined(__sparc_v9__)
#define udma_to_device_barrier() asm volatile("membar #StoreStore" ::: "memory")
#elif defined(__aarch64__)
#define udma_to_device_barrier() asm volatile("dsb st" ::: "memory");
#elif defined(__sparc__) || defined(__s390x__)
#define udma_to_device_barrier() asm volatile("" ::: "memory")
#else
#error No architecture specific memory barrier defines found!
#endif
/* Ensure that all ordered stores from the device are observable from the
CPU. This only makes sense after something that observes an ordered store
from the device - eg by reading a MMIO register or seeing that CPU memory is
updated.
This guarantees that all reads that follow the barrier see the ordered
stores that preceded the observation.
For instance, this would be used after testing a valid bit in a memory
that is a DMA target, to ensure that the following reads see the
data written before the MemWr TLP that set the valid bit.
*/
#if defined(__i386__)
#define udma_from_device_barrier() asm volatile("lock; addl $0,0(%%esp) " ::: "memory")
#elif defined(__x86_64__)
#define udma_from_device_barrier() asm volatile("lfence" ::: "memory")
#elif defined(__PPC64__)
#define udma_from_device_barrier() asm volatile("lwsync" ::: "memory")
#elif defined(__PPC__)
#define udma_from_device_barrier() asm volatile("sync" ::: "memory")
#elif defined(__ia64__)
#define udma_from_device_barrier() asm volatile("mf" ::: "memory")
#elif defined(__sparc_v9__)
#define udma_from_device_barrier() asm volatile("membar #LoadLoad" ::: "memory")
#elif defined(__aarch64__)
#define udma_from_device_barrier() asm volatile("dsb ld" ::: "memory");
#elif defined(__sparc__) || defined(__s390x__)
#define udma_from_device_barrier() asm volatile("" ::: "memory")
#else
#error No architecture specific memory barrier defines found!
#endif
/* Order writes to CPU memory so that a DMA device cannot view writes after
the barrier without also seeing all writes before the barrier. This does
not guarantee any writes are visible to DMA.
This would be used in cases where a DMA buffer might have a valid bit and
data, this barrier is placed after writing the data but before writing the
valid bit to ensure the DMA device cannot observe a set valid bit with
unwritten data.
Compared to udma_to_device_barrier() this barrier is not required to fence
anything but normal stores to normal malloc memory. Usage should be:
write_wqe
udma_to_device_barrier(); // Get user memory ready for DMA
wqe->addr = ...;
wqe->flags = ...;
udma_ordering_write_barrier(); // Guarantee WQE written in order
wqe->valid = 1;
*/
#define udma_ordering_write_barrier() udma_to_device_barrier()
/* Promptly flush writes to MMIO Write Cominbing memory.
This should be used after a write to WC memory. This is both a barrier
and a hint to the CPU to flush any buffers to reduce latency to TLP
generation.
This is not required to have any effect on CPU memory.
If done while holding a lock then the ordering of MMIO writes across CPUs
must be guaranteed to follow the natural ordering implied by the lock.
This must also act as a barrier that prevents write combining, eg
*wc_mem = 1;
mmio_flush_writes();
*wc_mem = 2;
Must always produce two MemWr TLPs, '1' and '2'. Without the barrier
the CPU is allowed to produce a single TLP '2'.
Note that there is no order guarantee for writes to WC memory without
barriers.
This is intended to be used in conjunction with WC memory to generate large
PCI-E MemWr TLPs from the CPU.
*/
#if defined(__i386__)
#define mmio_flush_writes() asm volatile("lock; addl $0,0(%%esp) " ::: "memory")
#elif defined(__x86_64__)
#define mmio_flush_writes() asm volatile("sfence" ::: "memory")
#elif defined(__PPC64__)
#define mmio_flush_writes() asm volatile("sync" ::: "memory")
#elif defined(__PPC__)
#define mmio_flush_writes() asm volatile("sync" ::: "memory")
#elif defined(__ia64__)
#define mmio_flush_writes() asm volatile("fwb" ::: "memory")
#elif defined(__sparc_v9__)
#define mmio_flush_writes() asm volatile("membar #StoreStore" ::: "memory")
#elif defined(__aarch64__)
#define mmio_flush_writes() asm volatile("dsb st" ::: "memory");
#elif defined(__sparc__) || defined(__s390x__)
#define mmio_flush_writes() asm volatile("" ::: "memory")
#else
#error No architecture specific memory barrier defines found!
#endif
/* Prevent WC writes from being re-ordered relative to other MMIO
writes. This should be used before a write to WC memory.
This must act as a barrier to prevent write re-ordering from different
memory types:
*mmio_mem = 1;
mmio_flush_writes();
*wc_mem = 2;
Must always produce a TLP '1' followed by '2'.
This barrier implies udma_to_device_barrier()
This is intended to be used in conjunction with WC memory to generate large
PCI-E MemWr TLPs from the CPU.
*/
#define mmio_wc_start() mmio_flush_writes()
/* Keep MMIO writes in order.
Currently we lack writel macros that universally guarantee MMIO
writes happen in order, like the kernel does. Even worse many
providers haphazardly open code writes to MMIO memory omitting even
volatile.
Until this can be fixed with a proper writel macro, this barrier
is a stand in to indicate places where MMIO writes should be switched
to some future writel.
*/
#define mmio_ordered_writes_hack() mmio_flush_writes()
/* Write Combining Spinlock primitive
Any access to a multi-value WC region must ensure that multiple cpus do not
write to the same values concurrently, these macros make that
straightforward and efficient if the choosen exclusion is a spinlock.
The spinlock guarantees that the WC writes issued within the critical
section are made visible as TLP to the device. The TLP must be seen by the
device strictly in the order that the spinlocks are acquired, and combining
WC writes between different sections is not permitted.
Use of these macros allow the fencing inside the spinlock to be combined
with the fencing required for DMA.
*/
static inline void mmio_wc_spinlock(pthread_spinlock_t *lock)
{
pthread_spin_lock(lock);
#if !defined(__i386__) && !defined(__x86_64__)
/* For x86 the serialization within the spin lock is enough to
* strongly order WC and other memory types. */
mmio_wc_start();
#endif
}
static inline void mmio_wc_spinunlock(pthread_spinlock_t *lock)
{
/* It is possible that on x86 the atomic in the lock is strong enough
* to force-flush the WC buffers quickly, and this SFENCE can be
* omitted too. */
mmio_flush_writes();
pthread_spin_unlock(lock);
}
#endif
@@ -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>
@@ -0,0 +1,12 @@
# $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
LIBADD+= osmcomp ibmad ibumad
@@ -0,0 +1,8 @@
# $FreeBSD$
PROG= dump_fts
SRCS= dump_fts.c
LIBADD= ibnetdisc
MAN= dump_fts.8
.include <bsd.prog.mk>
@@ -0,0 +1,7 @@
# $FreeBSD$
PROG= ibaddr
SRCS= ibaddr.c
MAN= ibaddr.8
.include <bsd.prog.mk>
@@ -0,0 +1,8 @@
# $FreeBSD$
PROG= ibcacheedit
SRCS= ibcacheedit.c
LIBADD= ibnetdisc
MAN= ibcacheedit.8
.include <bsd.prog.mk>
@@ -0,0 +1,7 @@
# $FreeBSD$
PROG= ibccconfig
SRCS= ibccconfig.c
MAN= ibccconfig.8
.include <bsd.prog.mk>
@@ -0,0 +1,7 @@
# $FreeBSD$
PROG= ibccquery
SRCS= ibccquery.c
MAN= ibccquery.8
.include <bsd.prog.mk>
@@ -0,0 +1,8 @@
# $FreeBSD$
PROG= iblinkinfo
SRCS= iblinkinfo.c
LIBADD= ibnetdisc
MAN= iblinkinfo.8
.include <bsd.prog.mk>
@@ -0,0 +1,7 @@
# $FreeBSD$
PROG= ibmirror
SRCS= ibmirror.c
MAN=
.include <bsd.prog.mk>
@@ -0,0 +1,8 @@
# $FreeBSD$
PROG= ibnetdiscover
SRCS= ibnetdiscover.c
LIBADD= ibnetdisc
MAN= ibnetdiscover.8
.include <bsd.prog.mk>
@@ -0,0 +1,7 @@
# $FreeBSD$
PROG= ibping
SRCS= ibping.c
MAN= ibping.8
.include <bsd.prog.mk>
@@ -0,0 +1,7 @@
# $FreeBSD$
PROG= ibportstate
SRCS= ibportstate.c
MAN= ibportstate.8
.include <bsd.prog.mk>
@@ -0,0 +1,8 @@
# $FreeBSD$
PROG= ibqueryerrors
SRCS= ibqueryerrors.c
LIBADD= ibnetdisc
MAN= ibqueryerrors.8
.include <bsd.prog.mk>
@@ -0,0 +1,7 @@
# $FreeBSD$
PROG= ibroute
SRCS= ibroute.c
MAN= ibroute.8
.include <bsd.prog.mk>
@@ -0,0 +1,7 @@
# $FreeBSD$
PROG= ibstat
SRCS= ibstat.c
MAN= ibstat.8
.include <bsd.prog.mk>
@@ -0,0 +1,7 @@
# $FreeBSD$
PROG= ibsysstat
SRCS= ibsysstat.c
MAN= ibsysstat.8
.include <bsd.prog.mk>
@@ -0,0 +1,7 @@
# $FreeBSD$
PROG= ibtracert
SRCS= ibtracert.c
MAN= ibtracert.8
.include <bsd.prog.mk>
@@ -0,0 +1,7 @@
# $FreeBSD$
PROG= perfquery
SRCS= perfquery.c
MAN= perfquery.8
.include <bsd.prog.mk>
@@ -0,0 +1,7 @@
# $FreeBSD$
PROG= saquery
SRCS= saquery.c
MAN= saquery.8
.include <bsd.prog.mk>
@@ -0,0 +1,7 @@
# $FreeBSD$
PROG= sminfo
SRCS= sminfo.c
MAN= sminfo.8
.include <bsd.prog.mk>
@@ -0,0 +1,7 @@
# $FreeBSD$
PROG= smpdump
SRCS= smpdump.c
MAN= smpdump.8
.include <bsd.prog.mk>
@@ -0,0 +1,7 @@
# $FreeBSD$
PROG= smpquery
SRCS= smpquery.c
MAN= smpquery.8
.include <bsd.prog.mk>
@@ -0,0 +1,7 @@
# $FreeBSD$
PROG= vendstat
SRCS= vendstat.c
MAN= vendstat.8
.include <bsd.prog.mk>
+125
View File
@@ -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 */
@@ -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.
.
@@ -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.
.
+214
View File
@@ -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.
.
@@ -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.
.
@@ -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.
.
@@ -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.
.
@@ -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.
.
+184
View File
@@ -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.
.
@@ -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.
.
@@ -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.
.
@@ -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.
.
+176
View File
@@ -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.
.
+177
View File
@@ -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.
.
@@ -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.
.
@@ -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.
.
+291
View File
@@ -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.
.
@@ -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.
.
+118
View File
@@ -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.
.
@@ -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.
.
@@ -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.
.
@@ -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.
.
@@ -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.
.
@@ -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.
.
@@ -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.
.
+380
View File
@@ -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.
.
+215
View File
@@ -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.
.
+207
View File
@@ -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.
.
@@ -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.
.
@@ -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.
.
@@ -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);
}
+168
View File
@@ -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);
}
@@ -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);
}
@@ -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);
}
@@ -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);
}
@@ -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;
}
@@ -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_ */
@@ -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);
}
@@ -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_ */
@@ -34,6 +34,6 @@
#ifndef _IBDIAG_VERSION_H_
#define _IBDIAG_VERSION_H_
#define IBDIAG_VERSION "1.4.4"
#define IBDIAG_VERSION "1.6.7"
#endif /* _IBDIAG_VERSION_H_ */
@@ -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);
}
@@ -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);
}
File diff suppressed because it is too large Load Diff
+286
View File
@@ -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);
}
@@ -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);
}
File diff suppressed because it is too large Load Diff
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2004-2008 Voltaire Inc. All rights reserved.
* 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
@@ -33,49 +34,44 @@
#if HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#endif /* HAVE_CONFIG_H */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdarg.h>
#include <time.h>
#include <string.h>
#include <inttypes.h>
#include <getopt.h>
#include <netinet/in.h>
#include <ctype.h>
#include <infiniband/common.h>
#include <infiniband/umad.h>
#include <infiniband/mad.h>
#include <complib/cl_nodenamemap.h>
#include "ibdiag_common.h"
static int dest_type = IB_DEST_LID;
static int brief;
static int verbose;
static int dump_all;
struct ibmad_port *srcport;
char *argv0 = "ibroute";
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, int *nports, uint64_t *guid,
uint8_t *sw, char *nd)
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};
uint8_t ni[IB_SMP_DATA_SIZE] = { 0 };
int type;
DEBUG("checking node type");
if (!smp_query(ni, portid, IB_ATTR_NODE_INFO, 0, 0)) {
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(nd, portid, IB_ATTR_NODE_DESC, 0, 0))
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);
@@ -86,7 +82,7 @@ check_switch(ib_portid_t *portid, int *nports, uint64_t *guid,
mad_decode_field(ni, IB_NODE_NPORTS_F, nports);
mad_decode_field(ni, IB_NODE_GUID_F, guid);
if (!smp_query(sw, portid, IB_ATTR_SWITCH_INFO, 0, 0))
if (!smp_query_via(sw, portid, IB_ATTR_SWITCH_INFO, 0, 0, srcport))
return "switch info failed: is a switch node?";
return 0;
@@ -94,18 +90,17 @@ check_switch(ib_portid_t *portid, int *nports, uint64_t *guid,
#define IB_MLIDS_IN_BLOCK (IB_SMP_DATA_SIZE/2)
int
dump_mlid(char *str, int strlen, int mlid, int nports,
uint16_t mft[16][IB_MLIDS_IN_BLOCK])
int dump_mlid(char *str, int strlen, unsigned mlid, unsigned nports,
uint16_t mft[16][IB_MLIDS_IN_BLOCK])
{
uint16_t mask;
int i, chunk, bit;
int nonzero = 0;
unsigned i, chunk, bit, nonzero = 0;
if (brief) {
int n = 0, chunks = ALIGN(nports + 1, 16) / 16;
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]);
mask = ntohs(mft[i][mlid % IB_MLIDS_IN_BLOCK]);
if (mask)
nonzero++;
n += snprintf(str + n, strlen - n, "%04hx", mask);
@@ -124,76 +119,90 @@ dump_mlid(char *str, int strlen, int mlid, int nports,
chunk = i / 16;
bit = i % 16;
mask = ntohs(mft[chunk][mlid%IB_MLIDS_IN_BLOCK]);
mask = ntohs(mft[chunk][mlid % IB_MLIDS_IN_BLOCK]);
if (mask)
nonzero++;
str[i*2] = (mask & (1 << bit)) ? 'x' : ' ';
str[i*2+1] = ' ';
str[i * 2] = (mask & (1 << bit)) ? 'x' : ' ';
str[i * 2 + 1] = ' ';
}
if (!nonzero && !dump_all) {
str[0] = 0;
return 0;
}
str[i*2] = 0;
str[i * 2] = 0;
return i * 2;
}
uint16_t mft[16][IB_MLIDS_IN_BLOCK];
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, int startlid, int endlid)
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 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;
int block, i, j, e, nports, cap, chunks;
int n = 0, startblock, lastblock;
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;
if (startlid < IB_MIN_MCAST_LID) {
IBWARN("illegal start mlid %x, set to %x", 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);
IBWARN("illegal end mlid %x, truncate to %x", endlid,
IB_MAX_MCAST_LID);
endlid = IB_MAX_MCAST_LID;
}
printf("Multicast mlids [0x%x-0x%x] of switch %s guid 0x%016" PRIx64 " (%s):\n",
startlid, endlid, portid2str(portid), nodeguid, clean_nodedesc(nd));
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++ = (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);
s += sprintf(s, "%d ", i % 10);
printf(" Ports: %s\n", str);
printf(" MLid\n");
}
if (verbose)
printf("Switch muticast mlids capability is 0x%d\n", cap);
if (ibverbose)
printf("Switch multicast mlid capability is %d top is 0x%x\n",
cap, top);
chunks = ALIGN(nports + 1, 16) / 16;
@@ -201,11 +210,20 @@ dump_multicast_tables(ib_portid_t *portid, int startlid, int endlid)
lastblock = endlid / IB_MLIDS_IN_BLOCK;
for (block = startblock; block <= lastblock; block++) {
for (j = 0; j < chunks; j++) {
mod = (block - IB_MIN_MCAST_LID/IB_MLIDS_IN_BLOCK) | (j << 28);
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(mft + j, portid, IB_ATTR_MULTICASTFORWTBL, mod, 0))
return "multicast forwarding table get failed";
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;
@@ -224,20 +242,24 @@ dump_multicast_tables(ib_portid_t *portid, int startlid, int endlid)
}
printf("%d %smlids dumped \n", n, dump_all ? "" : "valid ");
free(mapnd);
return 0;
}
int
dump_lid(char *str, int strlen, int lid, int valid)
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};
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], desc[64];
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;
@@ -246,7 +268,8 @@ dump_lid(char *str, int strlen, int lid, int valid)
if (lid <= last_port_lid) {
if (!valid)
return snprintf(str, strlen, ": (path #%d - illegal port)",
return snprintf(str, strlen,
": (path #%d - illegal port)",
lid - base_port_lid);
else if (!portguid)
return snprintf(str, strlen,
@@ -258,7 +281,8 @@ dump_lid(char *str, int strlen, int lid, int valid)
": (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));
mad_dump_val(IB_NODE_PORT_GUID_F, sguid,
sizeof sguid, &portguid));
}
}
@@ -268,11 +292,12 @@ dump_lid(char *str, int strlen, int lid, int valid)
portguid = 0;
lidport.lid = lid;
if (!smp_query(nd, &lidport, IB_ATTR_NODE_DESC, 0, 100) ||
!smp_query(pi, &lidport, IB_ATTR_PORT_INFO, 0, 100) ||
!smp_query(ni, &lidport, IB_ATTR_NODE_INFO, 0, 100))
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);
@@ -284,22 +309,30 @@ dump_lid(char *str, int strlen, int lid, int valid)
last_port_lid = baselid + (1 << lmc) - 1;
}
return 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),
mad_dump_val(IB_NODE_DESC_F, desc, sizeof desc, clean_nodedesc(nd)));
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 *dump_unicast_tables(ib_portid_t * portid, int startlid, int endlid)
{
char lft[IB_SMP_DATA_SIZE];
char nd[IB_SMP_DATA_SIZE];
uint8_t sw[IB_SMP_DATA_SIZE];
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, nports, top;
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;
@@ -310,12 +343,16 @@ dump_unicast_tables(ib_portid_t *portid, int startlid, int endlid)
endlid = top;
if (endlid > IB_MAX_UCAST_LID) {
IBWARN("ilegal lft top %d, truncate to %d", endlid, IB_MAX_UCAST_LID);
IBWARN("illegal lft top %d, truncate to %d", endlid,
IB_MAX_UCAST_LID);
endlid = IB_MAX_UCAST_LID;
}
printf("Unicast lids [0x%x-0x%x] of switch %s guid 0x%016" PRIx64 " (%s):\n",
startlid, endlid, portid2str(portid), nodeguid, clean_nodedesc(nd));
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);
@@ -323,10 +360,16 @@ dump_unicast_tables(ib_portid_t *portid, int startlid, int endlid)
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++) {
for (block = startblock; block < endblock; block++) {
int status;
DEBUG("reading block %d", block);
if (!smp_query(lft, portid, IB_ATTR_LINEARFORWTBL, block, 0))
return "linear forwarding table get failed";
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)
@@ -334,7 +377,7 @@ dump_unicast_tables(ib_portid_t *portid, int startlid, int endlid)
if (e > endlid + 1)
e = endlid + 1;
for (;i < e; i++) {
for (; i < e; i++) {
unsigned outport = lft[i % IB_SMP_DATA_SIZE];
unsigned valid = (outport <= nports);
@@ -347,141 +390,89 @@ dump_unicast_tables(ib_portid_t *portid, int startlid, int endlid)
}
printf("%d %slids dumped \n", n, dump_all ? "" : "valid ");
free(mapnd);
return 0;
}
void
usage(void)
static int process_opt(void *context, int ch, char *optarg)
{
char *basename;
if (!(basename = strrchr(argv0, '/')))
basename = argv0;
else
basename++;
fprintf(stderr, "Usage: %s [-d(ebug)] -a(ll) -n(o_dests) -v(erbose) -D(irect) -G(uid) -M(ulticast) -s smlid -V(ersion) -C ca_name -P ca_port "
"-t(imeout) timeout_ms] [<dest dr_path|lid|guid> [<startlid> [<endlid>]]]\n",
basename);
fprintf(stderr, "\n\tUnicast examples:\n");
fprintf(stderr, "\t\t%s 4\t# dump all lids with valid out ports of switch with lid 4\n", basename);
fprintf(stderr, "\t\t%s -a 4\t# same, but dump all lids, even with invalid out ports\n", basename);
fprintf(stderr, "\t\t%s -n 4\t# simple dump format - no destination resolving\n", basename);
fprintf(stderr, "\t\t%s 4 10\t# dump lids starting from 10\n", basename);
fprintf(stderr, "\t\t%s 4 0x10 0x20\t# dump lid range\n", basename);
fprintf(stderr, "\t\t%s -G 0x08f1040023\t# resolve switch by GUID\n", basename);
fprintf(stderr, "\t\t%s -D 0,1\t# resolve switch by direct path\n", basename);
fprintf(stderr, "\n\tMulticast examples:\n");
fprintf(stderr, "\t\t%s -M 4\t# dump all non empty mlids of switch with lid 4\n", basename);
fprintf(stderr, "\t\t%s -M 4 0xc010 0xc020\t# same, but with range\n", basename);
fprintf(stderr, "\t\t%s -M -n 4\t# simple dump format\n", basename);
exit(-1);
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 main(int argc, char **argv)
{
int mgmt_classes[3] = {IB_SMI_CLASS, IB_SMI_DIRECT_CLASS, IB_SA_CLASS};
ib_portid_t portid = {0};
ib_portid_t *sm_id = 0, sm_portid = {0};
int timeout;
int multicast = 0, startlid = 0, endlid = 0;
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;
char *ca = 0;
int ca_port = 0;
static char const str_opts[] = "C:P:t:s:danvDGMVhu";
static const struct option long_opts[] = {
{ "C", 1, 0, 'C'},
{ "P", 1, 0, 'P'},
{ "debug", 0, 0, 'd'},
{ "all", 0, 0, 'a'},
{ "no_dests", 0, 0, 'n'},
{ "verbose", 0, 0, 'v'},
{ "Direct", 0, 0, 'D'},
{ "Guid", 0, 0, 'G'},
{ "Multicast", 0, 0, 'M'},
{ "timeout", 1, 0, 't'},
{ "s", 1, 0, 's'},
{ "Version", 0, 0, 'V'},
{ "help", 0, 0, 'h'},
{ "usage", 0, 0, 'u'},
{ }
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,
};
argv0 = argv[0];
ibdiag_process_opts(argc, argv, NULL, "K", opts, process_opt,
usage_args, usage_examples);
while (1) {
int ch = getopt_long(argc, argv, str_opts, long_opts, NULL);
if ( ch == -1 )
break;
switch(ch) {
case 'C':
ca = optarg;
break;
case 'P':
ca_port = strtoul(optarg, 0, 0);
break;
case 'a':
dump_all++;
break;
case 'd':
ibdebug++;
break;
case 'D':
dest_type = IB_DEST_DRPATH;
break;
case 'G':
dest_type = IB_DEST_GUID;
break;
case 'M':
multicast++;
break;
case 'n':
brief++;
break;
case 's':
if (ib_resolve_portid_str(&sm_portid, optarg, IB_DEST_LID, 0) < 0)
IBERROR("can't resolve SM destination port %s", optarg);
sm_id = &sm_portid;
break;
case 't':
timeout = strtoul(optarg, 0, 0);
madrpc_set_timeout(timeout);
break;
case 'v':
madrpc_show_errors(1);
verbose++;
break;
case 'V':
fprintf(stderr, "%s %s\n", argv0, get_build_version() );
exit(-1);
default:
usage();
break;
}
}
argc -= optind;
argv += optind;
if (!argc)
usage();
ibdiag_show_usage();
if (argc > 1)
startlid = strtoul(argv[1], 0, 0);
if (argc > 2)
endlid = strtoul(argv[2], 0, 0);
madrpc_init(ca, ca_port, mgmt_classes, 3);
node_name_map = open_node_name_map(node_name_map_file);
if (!argc) {
if (ib_resolve_self(&portid, 0, 0) < 0)
IBERROR("can't resolve self addr");
} else {
if (ib_resolve_portid_str(&portid, argv[0], dest_type, sm_id) < 0)
IBERROR("can't resolve destination port %s", 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 (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);
@@ -489,7 +480,9 @@ main(int argc, char **argv)
err = dump_unicast_tables(&portid, startlid, endlid);
if (err)
IBERROR("dump tables: %s", err);
IBEXIT("dump tables: %s", err);
mad_rpc_close_port(srcport);
close_node_name_map(node_name_map);
exit(0);
}
@@ -0,0 +1,278 @@
/*
* Copyright (c) 2008 Lawrence Livermore National Security
* Copyright (c) 2008-2009 Voltaire Inc. All rights reserved.
* Copyright (c) 2009 HNR Consulting. All rights reserved.
* Copyright (c) 2011 Mellanox Technologies LTD. All rights reserved.
*
* Produced at Lawrence Livermore National Laboratory.
* Written by Ira Weiny <weiny2@llnl.gov>.
*
* This software is available to you under a choice of one of two
* licenses. You may choose to be licensed under the terms of the GNU
* General Public License (GPL) Version 2, available from the file
* COPYING in the main directory of this source tree, or the
* OpenIB.org BSD license below:
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above
* copyright notice, this list of conditions and the following
* disclaimer.
*
* - Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#define _GNU_SOURCE
#include <getopt.h>
#include <infiniband/mad.h>
#include <iba/ib_types.h>
#include "ibdiag_common.h"
struct ibmad_port *srcport;
/* for local link integrity */
int error_port = 1;
static uint16_t get_node_type(ib_portid_t * port)
{
uint16_t node_type = IB_NODE_TYPE_CA;
uint8_t data[IB_SMP_DATA_SIZE] = { 0 };
if (smp_query_via(data, port, IB_ATTR_NODE_INFO, 0, 0, srcport))
node_type = (uint16_t) mad_get_field(data, 0, IB_NODE_TYPE_F);
return node_type;
}
static uint32_t get_cap_mask(ib_portid_t * port)
{
uint8_t data[IB_SMP_DATA_SIZE] = { 0 };
uint32_t cap_mask = 0;
if (smp_query_via(data, port, IB_ATTR_PORT_INFO, 0, 0, srcport))
cap_mask = (uint32_t) mad_get_field(data, 0, IB_PORT_CAPMASK_F);
return cap_mask;
}
static void build_trap145(ib_mad_notice_attr_t * n, ib_portid_t * port)
{
n->generic_type = 0x80 | IB_NOTICE_TYPE_INFO;
n->g_or_v.generic.prod_type_lsb = cl_hton16(get_node_type(port));
n->g_or_v.generic.trap_num = cl_hton16(145);
n->issuer_lid = cl_hton16((uint16_t) port->lid);
n->data_details.ntc_145.new_sys_guid = cl_hton64(0x1234567812345678);
}
static void build_trap144_local(ib_mad_notice_attr_t * n, ib_portid_t * port)
{
n->generic_type = 0x80 | IB_NOTICE_TYPE_INFO;
n->g_or_v.generic.prod_type_lsb = cl_hton16(get_node_type(port));
n->g_or_v.generic.trap_num = cl_hton16(144);
n->issuer_lid = cl_hton16((uint16_t) port->lid);
n->data_details.ntc_144.lid = n->issuer_lid;
n->data_details.ntc_144.new_cap_mask = cl_hton32(get_cap_mask(port));
n->data_details.ntc_144.local_changes =
TRAP_144_MASK_OTHER_LOCAL_CHANGES;
}
static void build_trap144_nodedesc(ib_mad_notice_attr_t * n, ib_portid_t * port)
{
build_trap144_local(n, port);
n->data_details.ntc_144.change_flgs =
TRAP_144_MASK_NODE_DESCRIPTION_CHANGE;
}
static void build_trap144_linkspeed(ib_mad_notice_attr_t * n,
ib_portid_t * port)
{
build_trap144_local(n, port);
n->data_details.ntc_144.change_flgs =
TRAP_144_MASK_LINK_SPEED_ENABLE_CHANGE;
}
static void build_trap129(ib_mad_notice_attr_t * n, ib_portid_t * port)
{
n->generic_type = 0x80 | IB_NOTICE_TYPE_URGENT;
n->g_or_v.generic.prod_type_lsb = cl_hton16(get_node_type(port));
n->g_or_v.generic.trap_num = cl_hton16(129);
n->issuer_lid = cl_hton16((uint16_t) port->lid);
n->data_details.ntc_129_131.lid = n->issuer_lid;
n->data_details.ntc_129_131.pad = 0;
n->data_details.ntc_129_131.port_num = (uint8_t) error_port;
}
static void build_trap256_local(ib_mad_notice_attr_t * n, ib_portid_t * port)
{
n->generic_type = 0x80 | IB_NOTICE_TYPE_SECURITY;
n->g_or_v.generic.prod_type_lsb = cl_hton16(get_node_type(port));
n->g_or_v.generic.trap_num = cl_hton16(256);
n->issuer_lid = cl_hton16((uint16_t) port->lid);
n->data_details.ntc_256.lid = n->issuer_lid;
n->data_details.ntc_256.dr_slid = 0xffff;
n->data_details.ntc_256.method = 1;
n->data_details.ntc_256.attr_id = cl_ntoh16(0x15);
n->data_details.ntc_256.attr_mod = cl_ntoh32(0x12);
n->data_details.ntc_256.mkey = cl_ntoh64(0x1234567812345678);
}
static void build_trap256_lid(ib_mad_notice_attr_t * n, ib_portid_t * port)
{
build_trap256_local(n, port);
n->data_details.ntc_256.dr_trunc_hop = 0;
}
static void build_trap256_dr(ib_mad_notice_attr_t * n, ib_portid_t * port)
{
build_trap256_local(n, port);
n->data_details.ntc_256.dr_trunc_hop = 0x80 | 0x4;
n->data_details.ntc_256.dr_rtn_path[0] = 5;
n->data_details.ntc_256.dr_rtn_path[1] = 6;
n->data_details.ntc_256.dr_rtn_path[2] = 7;
n->data_details.ntc_256.dr_rtn_path[3] = 8;
}
static void build_trap257_258(ib_mad_notice_attr_t * n, ib_portid_t * port,
uint16_t trap_num)
{
n->generic_type = 0x80 | IB_NOTICE_TYPE_SECURITY;
n->g_or_v.generic.prod_type_lsb = cl_hton16(get_node_type(port));
n->g_or_v.generic.trap_num = cl_hton16(trap_num);
n->issuer_lid = cl_hton16((uint16_t) port->lid);
n->data_details.ntc_257_258.lid1 = cl_hton16(1);
n->data_details.ntc_257_258.lid2 = cl_hton16(2);
n->data_details.ntc_257_258.key = cl_hton32(0x12345678);
n->data_details.ntc_257_258.qp1 = cl_hton32(0x010101);
n->data_details.ntc_257_258.qp2 = cl_hton32(0x020202);
n->data_details.ntc_257_258.gid1.unicast.prefix = cl_ntoh64(0xf8c0000000000001);
n->data_details.ntc_257_258.gid1.unicast.interface_id = cl_ntoh64(0x1111222233334444);
n->data_details.ntc_257_258.gid2.unicast.prefix = cl_ntoh64(0xf8c0000000000001);
n->data_details.ntc_257_258.gid2.unicast.interface_id = cl_ntoh64(0x5678567812341234);
}
static void build_trap257(ib_mad_notice_attr_t * n, ib_portid_t * port)
{
build_trap257_258(n, port, 257);
}
static void build_trap258(ib_mad_notice_attr_t * n, ib_portid_t * port)
{
build_trap257_258(n, port, 258);
}
static int send_trap(void (*build) (ib_mad_notice_attr_t *, ib_portid_t *))
{
ib_portid_t sm_port;
ib_portid_t selfportid;
int selfport;
ib_rpc_t trap_rpc;
ib_mad_notice_attr_t notice;
if (resolve_self(ibd_ca, ibd_ca_port, &selfportid, &selfport, NULL))
IBEXIT("can't resolve self");
if (resolve_sm_portid(ibd_ca, ibd_ca_port, &sm_port))
IBEXIT("can't resolve SM destination port");
memset(&trap_rpc, 0, sizeof(trap_rpc));
trap_rpc.mgtclass = IB_SMI_CLASS;
trap_rpc.method = IB_MAD_METHOD_TRAP;
trap_rpc.trid = mad_trid();
trap_rpc.attr.id = NOTICE;
trap_rpc.datasz = IB_SMP_DATA_SIZE;
trap_rpc.dataoffs = IB_SMP_DATA_OFFS;
memset(&notice, 0, sizeof(notice));
build(&notice, &selfportid);
return mad_send_via(&trap_rpc, &sm_port, NULL, &notice, srcport);
}
typedef struct _trap_def {
char *trap_name;
void (*build_func) (ib_mad_notice_attr_t *, ib_portid_t *);
} trap_def_t;
static const trap_def_t traps[] = {
{"node_desc_change", build_trap144_nodedesc},
{"link_speed_enabled_change", build_trap144_linkspeed},
{"local_link_integrity", build_trap129},
{"sys_image_guid_change", build_trap145},
{"mkey_lid", build_trap256_lid},
{"mkey_dr", build_trap256_dr},
{"pkey", build_trap257},
{"qkey", build_trap258},
{NULL, NULL}
};
int process_send_trap(char *trap_name)
{
int i;
for (i = 0; traps[i].trap_name; i++)
if (strcmp(traps[i].trap_name, trap_name) == 0)
return send_trap(traps[i].build_func);
ibdiag_show_usage();
return 1;
}
int main(int argc, char **argv)
{
char usage_args[1024];
int mgmt_classes[2] = { IB_SMI_CLASS, IB_SMI_DIRECT_CLASS };
char *trap_name = NULL;
int i, n, rc;
n = sprintf(usage_args, "[<trap_name>] [<error_port>]\n"
"\nArgument <trap_name> can be one of the following:\n");
for (i = 0; traps[i].trap_name; i++) {
n += snprintf(usage_args + n, sizeof(usage_args) - n,
" %s\n", traps[i].trap_name);
if (n >= sizeof(usage_args))
exit(-1);
}
snprintf(usage_args + n, sizeof(usage_args) - n,
"\n default behavior is to send \"%s\"", traps[0].trap_name);
ibdiag_process_opts(argc, argv, NULL, "DGKL", NULL, NULL,
usage_args, NULL);
argc -= optind;
argv += optind;
trap_name = argv[0] ? argv[0] : traps[0].trap_name;
if (argc > 1)
error_port = atoi(argv[1]);
madrpc_show_errors(1);
srcport = mad_rpc_open_port(ibd_ca, ibd_ca_port, mgmt_classes, 2);
if (!srcport)
IBEXIT("Failed to open '%s' port '%d'", ibd_ca, ibd_ca_port);
smp_mkey_set(srcport, ibd_mkey);
rc = process_send_trap(trap_name);
mad_rpc_close_port(srcport);
return rc;
}
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2004-2008 Voltaire Inc. All rights reserved.
* 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
@@ -35,38 +36,23 @@
#if HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#endif /* HAVE_CONFIG_H */
#include <inttypes.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdarg.h>
#include <getopt.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <string.h>
#include <getopt.h>
#include <endian.h>
#include <byteswap.h>
#include <sys/poll.h>
#include <syslog.h>
#include <netinet/in.h>
#include <errno.h>
#include <infiniband/common.h>
#include <infiniband/umad.h>
#include <infiniband/mad.h>
#include <ibdiag_common.h>
static int debug;
char *argv0 = "ibstat";
static char *node_type_str[] = {
"???",
"CA",
@@ -75,18 +61,24 @@ static char *node_type_str[] = {
"iWARP RNIC"
};
static void
ca_dump(umad_ca_t *ca)
static void ca_dump(umad_ca_t * ca)
{
if (!ca->node_type)
return;
printf("%s '%s'\n", ((uint)ca->node_type <= IB_NODE_MAX ? node_type_str[ca->node_type] : "???"), ca->ca_name);
printf("\t%s type: %s\n", ((uint)ca->node_type <= IB_NODE_MAX ? node_type_str[ca->node_type] : "???"),ca->ca_type);
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%016llx\n", (long long unsigned)ntohll(ca->node_guid));
printf("\tSystem image GUID: 0x%016llx\n", (long long unsigned)ntohll(ca->system_guid));
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[] = {
@@ -108,8 +100,63 @@ static char *port_phy_state_str[] = {
"PhyTest"
};
static int
port_dump(umad_port_t *port, int alone)
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 = "";
@@ -123,19 +170,31 @@ port_dump(umad_port_t *port, int alone)
}
printf("%sPort %d:\n", hdrpre, port->portnum);
printf("%sState: %s\n", pre, (uint)port->state <= 4 ? port_state_str[port->state] : "???");
printf("%sPhysical state: %s\n", pre, (uint)port->state <= 7 ? port_phy_state_str[port->phys_state] : "???");
printf("%sRate: %d\n", pre, port->rate);
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, (unsigned)ntohl(port->capmask));
printf("%sPort GUID: 0x%016llx\n", pre, (long long unsigned)ntohll(port->port_guid));
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)
static int ca_stat(char *ca_name, int portnum, int no_ports)
{
umad_ca_t ca;
int r;
@@ -149,11 +208,15 @@ ca_stat(char *ca_name, int portnum, int no_ports)
if (!no_ports && portnum >= 0) {
if (portnum > ca.numports || !ca.ports[portnum]) {
IBWARN("%s: '%s' has no port number %d - max (%d)",
((uint)ca.node_type <= IB_NODE_MAX ? node_type_str[ca.node_type] : "???"),
ca_name, portnum, ca.numports);
((unsigned)ca.node_type <=
IB_NODE_MAX ? node_type_str[ca.node_type] :
"???"), ca_name, portnum, ca.numports);
return -1;
}
printf("%s: '%s'\n", ((uint)ca.node_type <= IB_NODE_MAX ? node_type_str[ca.node_type] : "???"), ca.ca_name);
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;
}
@@ -170,81 +233,67 @@ ca_stat(char *ca_name, int portnum, int no_ports)
return 0;
}
static int
ports_list(char names[][UMAD_CA_NAME_LEN], int n)
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)
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%016llx\n", (long long unsigned)ntohll(guids[i]));
printf("0x%016" PRIx64 "\n", ntohll(guids[i]));
return found;
}
void
usage(void)
static int list_only, short_format, list_ports;
static int process_opt(void *context, int ch, char *optarg)
{
fprintf(stderr, "Usage: %s [-d(ebug) -l(ist_of_cas) -s(hort) -p(ort_list) -V(ersion)] <ca_name> [portnum]\n", argv0);
fprintf(stderr, "\tExamples:\n");
fprintf(stderr, "\t\t%s -l # list all IB devices\n", argv0);
fprintf(stderr, "\t\t%s mthca0 2 # stat port 2 of 'mthca0'\n", argv0);
exit(-1);
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[])
int main(int argc, char *argv[])
{
char names[UMAD_MAX_DEVICES][UMAD_CA_NAME_LEN];
int dev_port = -1;
int list_only = 0, short_format = 0, list_ports = 0;
int n, i;
static char const str_opts[] = "dlspVhu";
static const struct option long_opts[] = {
{ "debug", 0, 0, 'd'},
{ "list_of_cas", 0, 0, 'l'},
{ "short", 0, 0, 's'},
{ "port_list", 0, 0, 'p'},
{ "Version", 0, 0, 'V'},
{ "help", 0, 0, 'h'},
{ "usage", 0, 0, 'u'},
{ }
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
};
argv0 = argv[0];
ibdiag_process_opts(argc, argv, NULL, "CDeGKLPsty", opts, process_opt,
usage_args, usage_examples);
while (1) {
int ch = getopt_long(argc, argv, str_opts, long_opts, NULL);
if ( ch == -1 )
break;
switch(ch) {
case 'd':
debug++;
break;
case 'l':
list_only++;
break;
case 's':
short_format++;
break;
case 'p':
list_ports++;
break;
case 'V':
fprintf(stderr, "%s %s\n", argv0, get_build_version() );
exit(-1);
default:
usage();
break;
}
}
argc -= optind;
argv += optind;
@@ -264,7 +313,8 @@ main(int argc, char *argv[])
if (i >= n)
IBPANIC("'%s' IB device can't be found", argv[0]);
strncpy(names[i], argv[0], sizeof names[i]);
strncpy(names[0], argv[0], sizeof(names[0])-1);
names[0][sizeof(names[0])-1] = '\0';
n = 1;
}
@@ -274,18 +324,11 @@ main(int argc, char *argv[])
return 0;
}
if (!list_only && argc) {
if (ca_stat(argv[0], dev_port, short_format) < 0)
IBPANIC("stat of IB device '%s' failed", argv[0]);
return 0;
}
for (i = 0; i < n; i++) {
if (list_only)
printf("%s\n", names[i]);
else
if (ca_stat(names[i], -1, short_format) < 0)
IBPANIC("stat of IB device '%s' failed", names[i]);
else if (ca_stat(names[i], dev_port, short_format) < 0)
IBPANIC("stat of IB device '%s' failed", names[i]);
}
return 0;
@@ -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);
}
@@ -1,5 +1,7 @@
/*
* Copyright (c) 2004-2008 Voltaire Inc. All rights reserved.
* 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
@@ -33,26 +35,25 @@
#if HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#endif /* HAVE_CONFIG_H */
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdarg.h>
#include <ctype.h>
#include <getopt.h>
#include <netinet/in.h>
#include <inttypes.h>
#include <errno.h>
#include <infiniband/common.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[] = {
@@ -64,12 +65,9 @@ static char *node_type_str[] = {
};
static int timeout = 0; /* ms */
static int verbose;
static int force;
static FILE *f;
char *argv0 = "ibtracert";
static char *node_name_map_file = NULL;
static nn_map_t *node_name_map = NULL;
@@ -94,6 +92,7 @@ struct Switch {
int mccap;
int linearFDBtop;
int fdb_base;
int enhsp0;
int8_t fdb[64];
char switchinfo[64];
};
@@ -116,16 +115,35 @@ struct Node {
Node *nodesdist[MAXHOPS];
uint64_t target_portguid;
static int
get_node(Node *node, Port *port, ib_portid_t *portid)
/*
* 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;
if (!smp_query(ni, portid, IB_ATTR_NODE_INFO, 0, timeout))
memset(ni, 0, sizeof(node->nodeinfo));
if (!smp_query_via(ni, portid, IB_ATTR_NODE_INFO, 0, timeout, srcport))
return -1;
if (!smp_query(nd, portid, IB_ATTR_NODE_DESC, 0, timeout))
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++) {
@@ -135,7 +153,8 @@ get_node(Node *node, Port *port, ib_portid_t *portid)
*s = ' ';
}
if (!smp_query(pi, portid, IB_ATTR_PORT_INFO, 0, timeout))
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);
@@ -148,50 +167,52 @@ get_node(Node *node, Port *port, ib_portid_t *portid)
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);
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)
static int switch_lookup(Switch * sw, ib_portid_t * portid, int lid)
{
void *si = sw->switchinfo, *fdb = sw->fdb;
if (!smp_query(si, portid, IB_ATTR_SWITCH_INFO, 0, timeout))
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)
if (lid >= sw->linearcap && lid > sw->linearFDBtop)
return -1;
if (!smp_query(fdb, portid, IB_ATTR_LINEARFORWTBL, lid / 64, timeout))
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]);
portid2str(portid), lid, sw->fdb[lid % 64]);
return sw->fdb[lid % 64];
}
static int
sameport(Port *a, Port *b)
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)
static int extend_dpath(ib_dr_path_t * path, int nextport)
{
if (path->cnt+2 >= sizeof(path->p))
if (path->cnt + 2 >= sizeof(path->p))
return -1;
++path->cnt;
path->p[path->cnt] = nextport;
path->p[path->cnt] = (uint8_t) nextport;
return path->cnt;
}
static void
dump_endnode(int dump, char *prompt, Node *node, Port *port)
static void dump_endnode(int dump, char *prompt, Node * node, Port * port)
{
char *nodename = NULL;
@@ -204,50 +225,57 @@ dump_endnode(int dump, char *prompt, Node *node, Port *port)
return;
}
nodename = remap_node_name(node_name_map, node->nodeguid, node->nodedesc);
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);
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)
static void dump_route(int dump, Node * node, int outport, Port * port)
{
char *nodename = NULL;
if (!dump && !verbose)
if (!dump && !ibverbose)
return;
nodename = remap_node_name(node_name_map, node->nodeguid, node->nodedesc);
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);
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)
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;
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));
@@ -266,26 +294,32 @@ find_route(ib_portid_t *from, ib_portid_t *to, int dump)
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 (port->state != 4)
if (is_port_inactive(node, port, &sw))
goto badport;
if (sameport(port, &toport))
break; /* found */
outport = portnum;
if (node->type == IB_NODE_SWITCH) {
DEBUG("switch node");
if ((outport = switch_lookup(&sw, from, to->lid)) < 0 ||
outport > node->numports)
goto badtbl;
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));
IBWARN("can't reach port at %s",
portid2str(from));
return -1;
}
if (outport == 0) {
@@ -298,10 +332,13 @@ find_route(ib_portid_t *from, ib_portid_t *to, int dump)
(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);
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 */
@@ -310,19 +347,33 @@ find_route(ib_portid_t *from, ib_portid_t *to, int dump)
from->drpath.cnt--;
} else {
ca_src = 1;
if (portnum && extend_dpath(&from->drpath, portnum) < 0)
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));
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];
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 (port->state != 4)
if (is_port_inactive(&nextnode, port, &sw))
goto badoutport;
node = &nextnode;
portnum = port->portnum;
@@ -338,22 +389,22 @@ find_route(ib_portid_t *from, ib_portid_t *to, int dump)
badport:
IBWARN("Bad port state found: node \"%s\" port %d state %d",
clean_nodedesc(node->nodedesc), portnum, port->state);
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);
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);
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
*/
@@ -361,12 +412,11 @@ find_route(ib_portid_t *from, ib_portid_t *to, int dump)
#define HASHGUID(guid) ((uint32_t)(((uint32_t)(guid) * 101) ^ ((uint32_t)((guid) >> 32) * 103)))
#define HTSZ 137
static int
insert_node(Node *new)
static int insert_node(Node * new)
{
static Node *nodestbl[HTSZ];
int hash = HASHGUID(new->nodeguid) % HTSZ;
Node *node ;
Node *node;
for (node = nodestbl[hash]; node; node = node->htnext)
if (node->nodeguid == new->nodeguid) {
@@ -380,15 +430,15 @@ insert_node(Node *new)
return 0;
}
static int
get_port(Port *port, int portnum, ib_portid_t *portid)
static int get_port(Port * port, int portnum, ib_portid_t * portid)
{
char portinfo[64];
char portinfo[64] = { 0 };
void *pi = portinfo;
port->portnum = portnum;
if (!smp_query(pi, portid, IB_ATTR_PORT_INFO, portnum, timeout))
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);
@@ -397,24 +447,23 @@ get_port(Port *port, int portnum, ib_portid_t *portid)
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);
portid2str(portid), portnum, port->lid, port->state,
port->physstate);
return 1;
}
static void
link_port(Port *port, Node *node)
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)
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 */
node->dist = -1; /* tag as target */
link_port(port, node);
dump_endnode(verbose, "found target", node, port);
dump_endnode(ibverbose, "found target", node, port);
return 1; /* found; */
}
@@ -422,7 +471,8 @@ new_node(Node *node, Port *port, ib_portid_t *path, int dist)
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);
VERBOSE("insert dist %d node %p port %d lid %d", dist, node,
port->portnum, port->lid);
link_port(port, node);
@@ -434,33 +484,36 @@ new_node(Node *node, Port *port, ib_portid_t *path, int dist)
return 0;
}
static int
switch_mclookup(Node *node, ib_portid_t *portid, int mlid, char *map)
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;
uint16_t *msets = (uint16_t *) mdb;
int maxsets, block, i, set;
memset(map, 0, 256);
if (!smp_query(si, portid, IB_ATTR_SWITCH_INFO, 0, timeout))
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)
if (mlid >= sw.mccap)
return -1;
block = mlid / 32;
maxsets = (node->numports + 15) / 16; /* round up */
maxsets = (node->numports + 15) / 16; /* round up */
for (set = 0; set < maxsets; set++) {
if (!smp_query(mdb, portid, IB_ATTR_MULTICASTFORWTBL,
block | (set << 28), timeout))
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++) {
@@ -469,7 +522,8 @@ switch_mclookup(Node *node, ib_portid_t *portid, int mlid, char *map)
*map = 1;
else
continue;
VERBOSE("Switch guid 0x%" PRIx64 ": mlid 0x%x is forwarded to port %d",
VERBOSE("Switch guid 0x%" PRIx64
": mlid 0x%x is forwarded to port %d",
node->nodeguid, mlid + 0xc000, i + set * 16);
}
}
@@ -480,8 +534,7 @@ switch_mclookup(Node *node, ib_portid_t *portid, int mlid, char *map)
/*
* Return 1 if found, 0 if not, -1 on errors.
*/
static Node *
find_mcpath(ib_portid_t *from, int mlid)
static Node *find_mcpath(ib_portid_t * from, int mlid)
{
Node *node, *remotenode;
Port *port, *remoteport;
@@ -493,25 +546,24 @@ find_mcpath(ib_portid_t *from, int mlid)
DEBUG("from %s", portid2str(from));
if (!(node = calloc(1, sizeof(Node))))
IBERROR("out of memory");
IBEXIT("out of memory");
if (!(port = calloc(1, sizeof(Port))))
IBERROR("out of memory");
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 */
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])
if (switch_mclookup(node, from, mlid, map) < 0 || !map[0])
return 0;
return node;
}
@@ -523,7 +575,8 @@ find_mcpath(ib_portid_t *from, int mlid)
path = &node->path;
VERBOSE("dist %d node %p", dist, node);
dump_endnode(verbose, "processing", node, node->ports);
dump_endnode(ibverbose, "processing", node,
node->ports);
memset(map, 0, sizeof(map));
@@ -533,8 +586,10 @@ find_mcpath(ib_portid_t *from, int mlid)
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);
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) */
@@ -542,8 +597,8 @@ find_mcpath(ib_portid_t *from, int mlid)
node->upport = leafport;
if (switch_mclookup(node, path, mlid, map) < 0) {
IBWARN("skipping bad Switch 0x%" PRIx64 "",
node->nodeguid);
IBWARN("skipping bad Switch 0x%" PRIx64
"", node->nodeguid);
continue;
}
}
@@ -557,10 +612,13 @@ find_mcpath(ib_portid_t *from, int mlid)
path->drpath.cnt--;
} else {
if (!(port = calloc(1, sizeof(Port))))
IBERROR("out of memory");
IBEXIT("out of memory");
if (get_port(port, i, path) < 0) {
IBWARN("can't reach node %s port %d", portid2str(path), i);
IBWARN
("can't reach node %s port %d",
portid2str(path), i);
free(port);
return 0;
}
@@ -568,24 +626,26 @@ find_mcpath(ib_portid_t *from, int mlid)
free(port);
continue;
}
#if 0
link_port(port, node);
#endif
if (extend_dpath(&path->drpath, i) < 0)
if (extend_dpath(&path->drpath, i) < 0) {
free(port);
return 0;
}
}
if (!(remotenode = calloc(1, sizeof(Node))))
IBERROR("out of memory");
IBEXIT("out of memory");
if (!(remoteport = calloc(1, sizeof(Port))))
IBERROR("out of memory");
IBEXIT("out of memory");
if (get_node(remotenode, remoteport, path) < 0) {
IBWARN("NodeInfo on %s port %d failed, skipping port",
portid2str(path), i);
IBWARN
("NodeInfo on %s port %d failed, skipping port",
portid2str(path), i);
path->drpath.cnt--; /* restore path */
free(remotenode);
free(remoteport);
@@ -596,15 +656,17 @@ find_mcpath(ib_portid_t *from, int mlid)
remotenode->upport = remoteport->portnum;
remoteport->remoteport = port;
if ((r = new_node(remotenode, remoteport, path, dist+1)) > 0)
if ((r = new_node(remotenode, remoteport, path,
dist + 1)) > 0)
return remotenode;
if (r == 0)
dump_endnode(verbose, "new remote",
remotenode, remoteport);
dump_endnode(ibverbose, "new remote",
remotenode, remoteport);
else if (remotenode->type == IB_NODE_SWITCH)
dump_endnode(2, "ERR: circle discovered at",
remotenode, remoteport);
dump_endnode(2,
"ERR: circle discovered at",
remotenode, remoteport);
path->drpath.cnt--; /* restore path */
}
@@ -614,8 +676,7 @@ find_mcpath(ib_portid_t *from, int mlid)
return 0; /* not found */
}
static uint64_t
find_target_portguid(ib_portid_t *to)
static uint64_t find_target_portguid(ib_portid_t * to)
{
Node tonode;
Port toport;
@@ -628,54 +689,58 @@ find_target_portguid(ib_portid_t *to)
return toport.portguid;
}
static void
dump_mcpath(Node *node, int dumplevel)
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);
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);
(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);
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);
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 */
/* 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);
(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)
static int resolve_lid(ib_portid_t * portid, const void *srcport)
{
uint8_t portinfo[64];
uint8_t portinfo[64] = { 0 };
uint16_t lid;
if (!smp_query_via(portinfo, portid, IB_ATTR_PORT_INFO, 0, 0, srcport))
@@ -687,164 +752,112 @@ static int resolve_lid(ib_portid_t *portid, const void *srcport)
return 0;
}
static void
usage(void)
static int dumplevel = 2, multicast, mlid;
static int process_opt(void *context, int ch, char *optarg)
{
char *basename;
if (!(basename = strrchr(argv0, '/')))
basename = argv0;
else
basename++;
fprintf(stderr, "Usage: %s [-d(ebug) -v(erbose) -D(irect) -G(uids) -n(o_info) -C ca_name -P ca_port "
"-s smlid -t(imeout) timeout_ms -m mlid --node-name-map node-name-map ] <src-addr> <dest-addr>\n",
basename);
fprintf(stderr, "\n\tUnicast examples:\n");
fprintf(stderr, "\t\t%s 4 16\t\t\t# show path between lids 4 and 16\n", basename);
fprintf(stderr, "\t\t%s -n 4 16\t\t# same, but using simple output format\n", basename);
fprintf(stderr, "\t\t%s -G 0x8f1040396522d 0x002c9000100d051\t# use guid addresses\n", basename);
fprintf(stderr, "\n\tMulticast example:\n");
fprintf(stderr, "\t\t%s -m 0xc000 4 16\t# show multicast path of mlid 0xc000 between lids 4 and 16\n", basename);
exit(-1);
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 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};
ib_portid_t *sm_id = 0, sm_portid = {0};
int dumplevel = 2, dest_type = IB_DEST_LID, multicast = 0, mlid = 0;
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;
int udebug = 0;
char *ca = 0;
int ca_port = 0;
static char const str_opts[] = "C:P:t:s:m:dvfDGnVhu";
static const struct option long_opts[] = {
{ "C", 1, 0, 'C'},
{ "P", 1, 0, 'P'},
{ "debug", 0, 0, 'd'},
{ "verbose", 0, 0, 'v'},
{ "force", 0, 0, 'f'},
{ "Direct", 0, 0, 'D'},
{ "Guids", 0, 0, 'G'},
{ "no_info", 0, 0, 'n'},
{ "timeout", 1, 0, 't'},
{ "s", 1, 0, 's'},
{ "m", 1, 0, 'm'},
{ "Version", 0, 0, 'V'},
{ "help", 0, 0, 'h'},
{ "usage", 0, 0, 'u'},
{ "node-name-map", 1, 0, 1},
{ }
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,
};
argv0 = argv[0];
ibdiag_process_opts(argc, argv, NULL, "DK", opts, process_opt,
usage_args, usage_examples);
f = stdout;
while (1) {
int ch = getopt_long(argc, argv, str_opts, long_opts, NULL);
if ( ch == -1 )
break;
switch(ch) {
case 1:
node_name_map_file = strdup(optarg);
break;
case 'C':
ca = optarg;
break;
case 'P':
ca_port = strtoul(optarg, 0, 0);
break;
case 'd':
ibdebug++;
madrpc_show_errors(1);
umad_debug(udebug);
udebug++;
break;
case 'D':
dest_type = IB_DEST_DRPATH;
break;
case 'G':
dest_type = IB_DEST_GUID;
break;
case 'm':
multicast++;
mlid = strtoul(optarg, 0, 0);
break;
case 'f':
force++;
break;
case 'n':
dumplevel = 1;
break;
case 's':
if (ib_resolve_portid_str(&sm_portid, optarg, IB_DEST_LID, 0) < 0)
IBERROR("can't resolve SM destination port %s", optarg);
sm_id = &sm_portid;
break;
case 't':
timeout = strtoul(optarg, 0, 0);
madrpc_set_timeout(timeout);
break;
case 'v':
madrpc_show_errors(1);
verbose++;
break;
case 'V':
fprintf(stderr, "%s %s\n", argv0, get_build_version() );
exit(-1);
default:
usage();
break;
}
}
argc -= optind;
argv += optind;
if (argc < 2)
usage();
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);
madrpc_init(ca, ca_port, mgmt_classes, 3);
node_name_map = open_node_name_map(node_name_map_file);
if (ib_resolve_portid_str(&src_portid, argv[0], dest_type, sm_id) < 0)
IBERROR("can't resolve source port %s", argv[0]);
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 (ib_resolve_portid_str(&dest_portid, argv[1], dest_type, sm_id) < 0)
IBERROR("can't resolve destination port %s", argv[1]);
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 (dest_type == IB_DEST_DRPATH) {
if (ibd_dest_type == IB_DEST_DRPATH) {
if (resolve_lid(&src_portid, NULL) < 0)
IBERROR("cannot resolve lid for port \'%s\'",
IBEXIT("cannot resolve lid for port \'%s\'",
portid2str(&src_portid));
if (resolve_lid(&dest_portid, NULL) < 0)
IBERROR("cannot resolve lid for port \'%s\'",
IBEXIT("cannot resolve lid for port \'%s\'",
portid2str(&dest_portid));
}
if (dest_portid.lid == 0 || src_portid.lid == 0) {
IBWARN("bad src/dest lid");
usage();
ibdiag_show_usage();
}
if (dest_type != IB_DEST_DRPATH) {
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)
IBERROR("can't find a route to the src port");
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)
IBERROR("can't find a route from src to dest");
IBEXIT("can't find a route from src to dest");
exit(0);
} else {
if (mlid < 0xc000)
@@ -852,14 +865,17 @@ main(int argc, char **argv)
}
if (!(target_portguid = find_target_portguid(&dest_portid)))
IBERROR("can't reach target lid %d", dest_portid.lid);
IBEXIT("can't reach target lid %d", dest_portid.lid);
if (!(endnode = find_mcpath(&src_portid, mlid)))
IBERROR("can't find a multicast route from src to dest");
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);
}
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2006 Voltaire, Inc. All rights reserved.
* 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
@@ -31,6 +31,10 @@
*
*/
#if HAVE_CONFIG_H
# include <config.h>
#endif /* HAVE_CONFIG_H */
#include <stdio.h>
#include <string.h>
#include <errno.h>
@@ -38,55 +42,40 @@
#include <infiniband/umad.h>
#include <infiniband/mad.h>
#include <infiniband/iba/ib_types.h>
#define info(fmt, arg...) fprintf(stderr, "INFO: " fmt, ##arg )
#define err(fmt, arg...) fprintf(stderr, "ERR: " fmt, ##arg )
#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, arg...) fprintf(stderr, "DBG: " fmt, ##arg )
#define dbg(fmt, ...) fprintf(stderr, "DBG: " fmt, ## __VA_ARGS__ )
#else
#define dbg(fmt, arg...)
#define dbg(fmt, ...)
#endif
#define TMO 100
/* Multicast Member Record Component Masks */
#define IB_MCR_COMPMASK_MGID (1ULL<<0)
#define IB_MCR_COMPMASK_PORT_GID (1ULL<<1)
#define IB_MCR_COMPMASK_QKEY (1ULL<<2)
#define IB_MCR_COMPMASK_MLID (1ULL<<3)
#define IB_MCR_COMPMASK_MTU_SEL (1ULL<<4)
#define IB_MCR_COMPMASK_MTU (1ULL<<5)
#define IB_MCR_COMPMASK_TCLASS (1ULL<<6)
#define IB_MCR_COMPMASK_PKEY (1ULL<<7)
#define IB_MCR_COMPMASK_RATE_SEL (1ULL<<8)
#define IB_MCR_COMPMASK_RATE (1ULL<<9)
#define IB_MCR_COMPMASK_LIFE_SEL (1ULL<<10)
#define IB_MCR_COMPMASK_LIFE (1ULL<<11)
#define IB_MCR_COMPMASK_SL (1ULL<<12)
#define IB_MCR_COMPMASK_FLOW (1ULL<<13)
#define IB_MCR_COMPMASK_HOP (1ULL<<14)
#define IB_MCR_COMPMASK_SCOPE (1ULL<<15)
#define IB_MCR_COMPMASK_JOIN_STATE (1ULL<<16)
#define IB_MCR_COMPMASK_PROXY (1ULL<<17)
static ibmad_gid_t mgid_ipoib = {
0xff, 0x12, 0x40, 0x1b, 0xff, 0xff, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff
};
uint64_t build_mcm_rec(uint8_t *data, ibmad_gid_t mgid, ibmad_gid_t port_gid)
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;
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)
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;
@@ -94,7 +83,7 @@ static void build_mcm_rec_umad(void *umad, ib_portid_t *dport, int method,
rpc.mgtclass = IB_SA_CLASS;
rpc.method = method;
rpc.attr.id = IB_SA_ATTR_MCRECORD;
rpc.attr.mod = 0; // ???
rpc.attr.mod = 0; // ???
rpc.mask = comp_mask;
rpc.datasz = IB_SA_DATA_SIZE;
rpc.dataoffs = IB_SA_DATA_OFFS;
@@ -102,8 +91,8 @@ static void build_mcm_rec_umad(void *umad, ib_portid_t *dport, int method,
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)
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;
@@ -111,8 +100,10 @@ static int rereg_send(int port, int agent, ib_portid_t *dport,
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 leave failed: %s\n", strerror(errno));
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,
@@ -121,26 +112,24 @@ static int rereg_send(int port, int agent, ib_portid_t *dport,
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)
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) {
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) {
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;
}
@@ -156,12 +145,13 @@ struct guid_trid {
uint64_t trid;
};
static int rereg_send_all(int port, int agent, ib_portid_t *dport,
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;
int i, ret;
unsigned i;
int ret;
info("rereg_send_all... cnt = %u\n", cnt);
@@ -172,59 +162,32 @@ static int rereg_send_all(int port, int agent, ib_portid_t *dport,
}
for (i = 0; i < cnt; i++) {
ret = rereg_port_gid(port, agent, dport, umad, len, list[i].gid);
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", list[i].guid);
" 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);
info("rereg_send_all: sent %u requests\n", cnt * 2);
free(umad);
return 0;
}
#if 0
static int rereg_mcm_rec_send(int port, int agent, ib_portid_t *dport, int cnt)
{
ib_portid_t portid;
ibmad_gid_t port_gid;
uint8_t *umad;
int len, ret = 0;
ib_resolve_self(&portid, NULL, &port_gid);
len = umad_size() + 256;
umad = calloc(1, len);
if (!umad) {
err("cannot alloc mem for umad: %s\n", strerror(errno));
return -1;
}
while(cnt--) {
if (!rereg_port_gid(port, agent, dport, umad, len, port_gid))
ret += 2;
}
free(umad);
return ret;
}
#endif
static int rereg_recv(int port, int agent, ib_portid_t *dport,
uint8_t *umad, int length, int tmo)
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) {
while ((ret = umad_recv(port, umad, &len, tmo)) < 0 &&
errno == ETIMEDOUT) {
if (retry++ > 3)
return 0;
}
@@ -232,22 +195,22 @@ static int rereg_recv(int port, int agent, ib_portid_t *dport,
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));
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,
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;
int i;
unsigned i;
info("rereg_recv_all...\n");
@@ -270,7 +233,7 @@ static int rereg_recv_all(int port, int agent, ib_portid_t *dport,
dbg("MAD status %x, method %x\n", status, method);
if (status &&
(method&0x7f) == (IB_MAD_METHOD_GET_RESPONSE&0x7f)) {
(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)
@@ -280,12 +243,14 @@ static int rereg_recv_all(int port, int agent, ib_portid_t *dport,
trid);
continue;
}
info("guid 0x%016" PRIx64 ": method = %x status = %x. Resending\n",
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);
list[i].trid =
mad_get_field64(umad_get_mad(umad), 0,
IB_MAD_TRID_F);
}
}
@@ -295,13 +260,14 @@ static int rereg_recv_all(int port, int agent, ib_portid_t *dport,
return 0;
}
static int rereg_query_all(int port, int agent, ib_portid_t *dport,
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;
int i, ret;
unsigned i;
int ret;
info("rereg_query_all...\n");
@@ -311,7 +277,7 @@ static int rereg_query_all(int port, int agent, ib_portid_t *dport,
return -1;
}
for ( i = 0; i < cnt; i++ ) {
for (i = 0; i < cnt; i++) {
ret = rereg_send(port, agent, dport, umad, len,
IB_MAD_METHOD_GET, list[i].gid);
if (ret < 0) {
@@ -341,57 +307,23 @@ static int rereg_query_all(int port, int agent, ib_portid_t *dport,
return 0;
}
#if 0
static int rereg_mcm_rec_recv(int port, int agent, int cnt)
{
uint8_t *umad, *mad;
int len = umad_size() + 256;
int i;
umad = calloc(1, len);
if (!umad) {
err("cannot alloc mem for umad: %s\n", strerror(errno));
return -1;
}
for ( i = 0; i < cnt; i++ ) {
int retry;
retry = 0;
while (umad_recv(port, umad, &len, TMO) < 0 &&
errno == ETIMEDOUT)
if (retry++ > 3) {
err("umad_recv %d failed: %s\n",
i, strerror(errno));
free(umad);
return -1;
}
dbg("umad_recv %d (retries %d), tid = 0x%016" PRIx64 ": len = %d, status = %d\n",
i, retry,
mad_get_field64(umad_get_mad(umad), 0, IB_MAD_TRID_F),
len, umad_status(umad));
mad = umad_get_mad(umad);
}
free(umad);
return 0;
}
#endif
#define MAX_CLIENTS 50
static int rereg_and_test_port(char *guid_file, int port, int agent, ib_portid_t *dport, int timeout)
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(0xfe80000000000000llu);
uint64_t guid = htonll(0x0002c90200223825llu);
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));
err("cannot alloc mem for guid/trid list: %s\n",
strerror(errno));
return -1;
}
@@ -427,7 +359,7 @@ static int rereg_and_test_port(char *guid_file, int port, int agent, ib_portid_t
int main(int argc, char **argv)
{
char *guid_file = "port_guids.list";
int mgmt_classes[2] = {IB_SMI_CLASS, IB_SMI_DIRECT_CLASS};
int mgmt_classes[2] = { IB_SMI_CLASS, IB_SMI_DIRECT_CLASS };
ib_portid_t dport_id;
int port, agent;
uint8_t *umad, *mad;
@@ -436,48 +368,26 @@ int main(int argc, char **argv)
if (argc > 1)
guid_file = argv[1];
madrpc_init(NULL, 0, mgmt_classes, 2);
srcport = mad_rpc_open_port(NULL, 0, mgmt_classes, 2);
if (!srcport)
err("Failed to open port");
#if 1
ib_resolve_smlid(&dport_id, TMO);
#else
memset(&dport_id, 0, sizeof(dport_id));
dport_id.lid = 1;
#endif
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;
}
#if 1
port = madrpc_portid();
#else
ret = umad_init();
port = umad_open_port(NULL, 0);
if (port < 0) {
err("umad_open_port failed: %s\n", strerror(errno));
return port;
}
#endif
port = mad_rpc_portid(srcport);
agent = umad_register(port, IB_SA_CLASS, 2, 0, NULL);
#if 0
int cnt;
cnt = rereg_mcm_rec_send(port, agent, &dport_id, cnt);
rereg_recv_all(port, agent, &dport_id);
#else
rereg_and_test_port(guid_file, port, agent, &dport_id, TMO);
#endif
mad = umad_get_mad(umad);
free(umad);
File diff suppressed because it is too large Load Diff
@@ -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;
}
File diff suppressed because it is too large Load Diff
+162
View File
@@ -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);
}
+318
View File
@@ -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;
}
@@ -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);
}
@@ -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);
}
-1
View File
@@ -1 +0,0 @@
Chelsio Communications, Inc.
-29
View File
@@ -1,29 +0,0 @@
Copyright (c) 2010-2013. Chelsio Communications. 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.
File diff suppressed because it is too large Load Diff
+19
View File
@@ -0,0 +1,19 @@
# $FreeBSD$
.PATH: ${.CURDIR}
SHLIBDIR?= /usr/lib
LIB= cxgb4
SHLIB_MAJOR= 1
MK_PROFILE= no
SRCS= \
cq.c \
dev.c \
qp.c \
verbs.c
LIBADD= ibverbs pthread
CFLAGS+= -I${.CURDIR}
.include <bsd.lib.mk>
-19
View File
@@ -1,19 +0,0 @@
Introduction
============
libcxgb4 is a userspace driver for the Chelsio T5 iWARP RNICs. It works
as a plug-in module for libibverbs that allows programs to use Chelsio
RNICs directly from userspace. See the libibverbs package for more
information.
Using libcxgb4
===================
libcxgb4 will be loaded and used automatically by programs linked with
libibverbs. The iw_cxgbe kernel module must be loaded for Chelsio RNIC
devices to be detected and used.
Supported Hardware
==================
libcxgb4 supports the Chelsio T5 family of adapters.
+6
View File
@@ -0,0 +1,6 @@
/* $FreeBSD$ */
#define ENODATA ECONNREFUSED
#define likely(x) __predict_true(x)
#define unlikely(x) __predict_false(x)
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2006-2014 Chelsio, Inc. All rights reserved.
* Copyright (c) 2006-2016 Chelsio, 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
@@ -29,15 +29,12 @@
* 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 <config.h>
#include <stdio.h>
#include <syslog.h>
#include <pthread.h>
#include <sys/errno.h>
#include <netinet/in.h>
#include <infiniband/opcode.h>
#include "libcxgb4.h"
#include "cxgb4-abi.h"
@@ -49,12 +46,12 @@ static void insert_recv_cqe(struct t4_wq *wq, struct t4_cq *cq)
PDBG("%s wq %p cq %p sw_cidx %u sw_pidx %u\n", __func__,
wq, cq, cq->sw_cidx, cq->sw_pidx);
memset(&cqe, 0, sizeof(cqe));
cqe.header = cpu_to_be32(V_CQE_STATUS(T4_ERR_SWFLUSH) |
cqe.header = htobe32(V_CQE_STATUS(T4_ERR_SWFLUSH) |
V_CQE_OPCODE(FW_RI_SEND) |
V_CQE_TYPE(0) |
V_CQE_SWCQE(1) |
V_CQE_QPID(wq->sq.qid));
cqe.bits_type_ts = cpu_to_be64(V_CQE_GENBIT((u64)cq->gen));
cqe.bits_type_ts = htobe64(V_CQE_GENBIT((u64)cq->gen));
cq->sw_queue[cq->sw_pidx] = cqe;
t4_swcq_produce(cq);
}
@@ -82,13 +79,13 @@ static void insert_sq_cqe(struct t4_wq *wq, struct t4_cq *cq,
PDBG("%s wq %p cq %p sw_cidx %u sw_pidx %u\n", __func__,
wq, cq, cq->sw_cidx, cq->sw_pidx);
memset(&cqe, 0, sizeof(cqe));
cqe.header = cpu_to_be32(V_CQE_STATUS(T4_ERR_SWFLUSH) |
cqe.header = htobe32(V_CQE_STATUS(T4_ERR_SWFLUSH) |
V_CQE_OPCODE(swcqe->opcode) |
V_CQE_TYPE(1) |
V_CQE_SWCQE(1) |
V_CQE_QPID(wq->sq.qid));
CQE_WRID_SQ_IDX(&cqe) = swcqe->idx;
cqe.bits_type_ts = cpu_to_be64(V_CQE_GENBIT((u64)cq->gen));
cqe.bits_type_ts = htobe64(V_CQE_GENBIT((u64)cq->gen));
cq->sw_queue[cq->sw_pidx] = cqe;
t4_swcq_produce(cq);
}
@@ -151,7 +148,7 @@ static void flush_completed_wrs(struct t4_wq *wq, struct t4_cq *cq)
PDBG("%s moving cqe into swcq sq idx %u cq idx %u\n",
__func__, cidx, cq->sw_pidx);
swsqe->cqe.header |= htonl(V_CQE_SWCQE(1));
swsqe->cqe.header |= htobe32(V_CQE_SWCQE(1));
cq->sw_queue[cq->sw_pidx] = swsqe->cqe;
t4_swcq_produce(cq);
swsqe->flushed = 1;
@@ -167,8 +164,8 @@ static void create_read_req_cqe(struct t4_wq *wq, struct t4_cqe *hw_cqe,
struct t4_cqe *read_cqe)
{
read_cqe->u.scqe.cidx = wq->sq.oldest_read->idx;
read_cqe->len = ntohl(wq->sq.oldest_read->read_len);
read_cqe->header = htonl(V_CQE_QPID(CQE_QPID(hw_cqe)) |
read_cqe->len = be32toh(wq->sq.oldest_read->read_len);
read_cqe->header = htobe32(V_CQE_QPID(CQE_QPID(hw_cqe)) |
V_CQE_SWCQE(SW_CQE(hw_cqe)) |
V_CQE_OPCODE(FW_RI_READ_REQ) |
V_CQE_TYPE(1));
@@ -275,7 +272,7 @@ void c4iw_flush_hw_cq(struct c4iw_cq *chp)
} else {
swcqe = &chp->cq.sw_queue[chp->cq.sw_pidx];
*swcqe = *hw_cqe;
swcqe->header |= cpu_to_be32(V_CQE_SWCQE(1));
swcqe->header |= htobe32(V_CQE_SWCQE(1));
t4_swcq_produce(&chp->cq);
}
next_cqe:
@@ -322,11 +319,11 @@ void c4iw_count_rcqes(struct t4_cq *cq, struct t4_wq *wq, int *count)
static void dump_cqe(void *arg)
{
u64 *p = arg;
syslog(LOG_NOTICE, "cxgb4 err cqe %016lx %016lx %016lx %016lx\n",
be64_to_cpu(p[0]),
be64_to_cpu(p[1]),
be64_to_cpu(p[2]),
be64_to_cpu(p[3]));
syslog(LOG_NOTICE, "cxgb4 err cqe %016llx %016llx %016llx %016llx\n",
(long long)be64toh(p[0]),
(long long)be64toh(p[1]),
(long long)be64toh(p[2]),
(long long)be64toh(p[3]));
}
/*
@@ -428,6 +425,11 @@ static int poll_cq(struct t4_wq *wq, struct t4_cq *cq, struct t4_cqe *cqe,
advance_oldest_read(wq);
}
if (CQE_OPCODE(hw_cqe) == FW_RI_TERMINATE) {
ret = -EAGAIN;
goto skip_cqe;
}
if (CQE_STATUS(hw_cqe) || t4_wq_in_error(wq)) {
*cqe_flushed = (CQE_STATUS(hw_cqe) == T4_ERR_SWFLUSH);
wq->error = 1;
@@ -439,11 +441,6 @@ static int poll_cq(struct t4_wq *wq, struct t4_cq *cq, struct t4_cqe *cqe,
goto proc_cqe;
}
if (CQE_OPCODE(hw_cqe) == FW_RI_TERMINATE) {
ret = -EAGAIN;
goto skip_cqe;
}
/*
* RECV completion.
*/
@@ -463,7 +460,7 @@ static int poll_cq(struct t4_wq *wq, struct t4_cq *cq, struct t4_cqe *cqe,
}
if (unlikely((CQE_WRID_MSN(hw_cqe) != (wq->rq.msn)))) {
t4_set_wq_in_error(wq);
hw_cqe->header |= htonl(V_CQE_STATUS(T4_ERR_MSN));
hw_cqe->header |= htobe32(V_CQE_STATUS(T4_ERR_MSN));
goto proc_cqe;
}
goto proc_cqe;
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2006-2014 Chelsio, Inc. All rights reserved.
* Copyright (c) 2006-2016 Chelsio, 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
@@ -32,6 +32,7 @@
#ifndef IWCH_ABI_H
#define IWCH_ABI_H
#include <stdint.h>
#include <infiniband/kern-abi.h>
struct c4iw_alloc_ucontext_resp {

Some files were not shown because too many files have changed in this diff Show More