[ofa-general] ***SPAM*** Re: [PATCH 1/3 - no ibcommon] Create a new library libibnetdisc
Sasha Khapyorsky
sashak at voltaire.com
Wed Jan 21 06:49:23 PST 2009
On 15:47 Fri 09 Jan , Ira Weiny wrote:
>
> Signed-off-by: weiny2 at llnl.gov <weiny2 at llnl.gov>
Some comments...
> diff --git a/infiniband-diags/Makefile.am b/infiniband-diags/Makefile.am
> index c22ba5e..8e8c3c1 100644
> --- a/infiniband-diags/Makefile.am
> +++ b/infiniband-diags/Makefile.am
> @@ -1,3 +1,4 @@
> +SUBDIRS = libibnetdisc
>
> INCLUDES = -I$(top_builddir)/include/ -I$(srcdir)/include -I$(includedir) -I$(includedir)/infiniband
>
> diff --git a/infiniband-diags/configure.in b/infiniband-diags/configure.in
> index 58eea0a..c5b437d 100644
> --- a/infiniband-diags/configure.in
> +++ b/infiniband-diags/configure.in
> @@ -48,7 +48,7 @@ fi
>
> dnl Checks for header files.
> AC_HEADER_STDC
> -AC_CHECK_HEADERS([stdlib.h string.h unistd.h fcntl.h inttypes.h netinet/in.h sys/ioctl.h syslog.h])
> +AC_CHECK_HEADERS([stdlib.h string.h unistd.h fcntl.h inttypes.h netinet/in.h sys/ioctl.h])
> if test "$disable_libcheck" != "yes"
> then
> AC_CHECK_HEADER(infiniband/umad.h, [],
> @@ -70,7 +70,7 @@ AC_C_CONST
> dnl Check if we should include test utilities
> AC_MSG_CHECKING(for --enable-test-utils)
> AC_ARG_ENABLE(test-utils,
> -[ --enable-test-utils build additional test utilities],
> +[ --enable-test-utils build additional test utilities (default=no)],
> [case "${enableval}" in
> yes) tutils=yes ;;
> no) tutils=no ;;
> @@ -140,6 +140,23 @@ IBSCRIPTPATH_TMP2="`echo $IBSCRIPTPATH_TMP1 | sed 's/^NONE/$ac_default_prefix/'`
> IBSCRIPTPATH="`eval echo $IBSCRIPTPATH_TMP2`"
> AC_SUBST(IBSCRIPTPATH)
>
> +dnl Begin libibnetdisc stuff
> +AC_CHECK_HEADERS([stdint.h])
BTW (not related to the patch), in current grouping.c code I see
#include <stdint.h>
#include <inttypes.h>
inttypes.h by itself includes stdint.h and as addition declares related
printf formats such as PRIx64, etc.. So it is not really necessary to
include both.
> +AC_CHECK_FUNCS([strtoull])
> +
> +ibnetdisc_api_version=`grep LIBVERSION $srcdir/libibnetdisc/libibnetdisc.ver | sed 's/LIBVERSION=//'`
> +if test -z $ibnetdisc_api_version; then
> + echo "FAILED to find $srcdir/libibnetdisc/libibnetdisc.ver"
> + exit 1
> +fi
> +AC_SUBST(ibnetdisc_api_version)
> +AC_DEFINE_UNQUOTED(API_VERSION,
> + ["$ibnetdisc_api_version"],
> + [The API version of this library])
Where do you plan to use it (API_VERSION)?
> +
> +dnl End libibnetdisc stuff
> +
> +
> AC_CONFIG_FILES([\
> Makefile \
> infiniband-diags.spec \
> @@ -160,6 +177,7 @@ AC_CONFIG_FILES([\
> scripts/ibhosts \
> scripts/ibnodes \
> scripts/ibswitches \
> - scripts/ibrouters
> + scripts/ibrouters \
> + libibnetdisc/Makefile
> ])
> AC_OUTPUT
> diff --git a/infiniband-diags/libibnetdisc/Makefile.am b/infiniband-diags/libibnetdisc/Makefile.am
> new file mode 100644
> index 0000000..8e0e16b
> --- /dev/null
> +++ b/infiniband-diags/libibnetdisc/Makefile.am
> @@ -0,0 +1,62 @@
> +
> +#SUBDIRS = .
> +
> +INCLUDES = -I$(srcdir)/include -I$(includedir) -I$(includedir)/infiniband
> +
> +lib_LTLIBRARIES = libibnetdisc.la
> +sbin_PROGRAMS =
> +
> +if ENABLE_TEST_UTILS
> +sbin_PROGRAMS += test/ibnetdisctest \
> + test/iblinkinfotest \
> + test/testleaks
> +endif
> +
> +DBGFLAGS = -g
> +
> +if HAVE_LD_VERSION_SCRIPT
> +libibnetdisc_version_script = -Wl,--version-script=$(srcdir)/src/libibnetdisc.map
> +else
> +libibnetdisc_version_script =
> +endif
> +
> +libibnetdisc_la_SOURCES = src/ibnetdisc.c src/chassis.c src/chassis.h
> +libibnetdisc_la_CFLAGS = -Wall $(DBGFLAGS)
> +libibnetdisc_la_LDFLAGS = -version-info $(ibnetdisc_api_version) \
> + -export-dynamic $(libibnetdisc_version_script) \
> + -losmcomp -libmad
> +libibnetdisc_la_DEPENDENCIES = $(srcdir)/src/libibnetdisc.map
> +
> +libibnetdiscincludedir = $(includedir)/infiniband
> +
> +test_ibnetdisctest_SOURCES = test/ibnetdisctest.c
> +test_ibnetdisctest_CFLAGS = -Wall $(DBGFLAGS)
> +test_ibnetdisctest_LDFLAGS = -libnetdisc
> +
> +test_iblinkinfotest_SOURCES = test/iblinkinfotest.c
> +test_iblinkinfotest_CFLAGS = -Wall $(DBGFLAGS)
> +test_iblinkinfotest_LDFLAGS = -libnetdisc
> +
> +test_testleaks_SOURCES = test/testleaks.c
> +test_testleaks_CFLAGS = -Wall $(DBGFLAGS)
> +test_testleaks_LDFLAGS = -libnetdisc
> +
> +libibnetdiscinclude_HEADERS = $(srcdir)/include/infiniband/ibnetdisc.h
> +
> +man_MANS = man/ibnd_debug.3 \
> + man/ibnd_destroy_fabric.3 \
> + man/ibnd_discover_fabric.3 \
> + man/ibnd_find_node_dr.3 \
> + man/ibnd_find_node_guid.3 \
> + man/ibnd_iter_nodes.3 \
> + man/ibnd_iter_nodes_type.3 \
> + man/ibnd_linkspeed_str.3 \
> + man/ibnd_linkstate_str.3 \
> + man/ibnd_linkwidth_str.3 \
> + man/ibnd_node_type_str.3 \
> + man/ibnd_physstate_str.3 \
> + man/ibnd_update_node.3 \
> + man/ibnd_show_progress.3
> +
> +EXTRA_DIST = $(srcdir)/src/libibnetdisc.map libibnetdisc.ver autogen.sh
> +
> diff --git a/infiniband-diags/libibnetdisc/include/infiniband/ibnetdisc.h b/infiniband-diags/libibnetdisc/include/infiniband/ibnetdisc.h
> new file mode 100644
> index 0000000..773c64b
> --- /dev/null
> +++ b/infiniband-diags/libibnetdisc/include/infiniband/ibnetdisc.h
> @@ -0,0 +1,282 @@
> +/*
> + * Copyright (c) 2008 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.
> + *
> + */
> +
> +#ifndef _IBNETDISC_H_
> +#define _IBNETDISC_H_
> +
> +#include <stdio.h>
> +#include <infiniband/mad.h>
> +
> +#define MAXHOPS 63
> +
> +/* HASH table defines */
> +#define HASHGUID(guid) ((uint32_t)(((uint32_t)(guid) * 101) ^ ((uint32_t)((guid) >> 32) * 103)))
> +#define HTSZ 137
This is used only in ./libibnetdisc/src/ibnetdisc.c, if so should it be
in public header file?
> +
> +#define IBND_DEBUG(...) \
> + if (ibdebug) { \
> + printf("%s:%d; ", __FILE__, __LINE__); \
> + printf(__VA_ARGS__); \
> + }
> +#define IBND_ERROR(...) \
> + { \
> + fprintf(stderr, "%s:%d; ", __FILE__, __LINE__); \
> + fprintf(stderr, __VA_ARGS__); \
> + }
This can be done as
#define IBND_ERROR(fmt, ...) \
fprintf(stderr, "%s:%u: " fmt, __FILE__, __LINE__, ## __VA_ARGS__)
> +
> +/** =========================================================================
> + * ENUM definitions
> + */
> +typedef enum {
> + IBND_CA_NODE = 1,
> + IBND_SWITCH_NODE = 2,
> + IBND_ROUTER_NODE = 3
> +} ibnd_node_type_t;
infiniband/mad.h has IB_NODE_CA, IB_NODE_SWITCH, IB_NODE_ROUTER
definitions already.
> +
> +typedef enum {
> + IBND_LINK_DOWN = 1,
> + IBND_LINK_INIT = 2,
> + IBND_LINK_ARMED = 3,
> + IBND_LINK_ACTIVE = 4
> +} ibnd_link_state_t;
> +
> +/** =========================================================================
> + * Node
> + */
> +typedef struct switch_info {
> + int smaenhsp0;
> +} ibnd_switch_info_t;
> +
> +typedef struct node_info {
> + int base_ver;
> + int class_ver;
> + int type;
> + int numports;
> + uint64_t sysimgguid;
> + uint64_t nodeguid;
> + uint64_t nodeportguid;
> + uint16_t partition_cap;
> + uint32_t devid;
> + uint32_t revision;
> + int localport;
> + uint32_t vendid;
> +} ibnd_node_info_t;
Discussed in another thread about those definitions...
> +
> +struct ib_fabric; /* forward declare */
> +struct chassis; /* forward declare */
> +struct port; /* forward declare */
> +
> +typedef struct node {
> + struct node *next; /* all node list in fabric */
> + struct ib_fabric *fabric; /* the fabric node belongs to */
> +
> + ib_portid_t path_portid; /* path from "from_node" */
> + int dist; /* num of hops from "from_node" */
> + int smalid;
> + int smalmc;
> + ibnd_switch_info_t sw_info;
> + ibnd_node_info_t info;
> + char nodedesc[64];
> + struct port **ports; /* in order array of port pointers */
> + /* the size of this array is info.numports + 1 */
> + /* items MAY BE NULL! (ie 0 == switches only) */
> +
> + /* chassis info */
> + struct node *next_chassis_node; /* next node in ibnd_chassis_t->nodes */
> + struct chassis *chassis; /* if != NULL the chassis this node belongs to */
> + unsigned char ch_type;
> + unsigned char ch_anafanum;
> + unsigned char ch_slotnum;
> + unsigned char ch_slot;
> +} ibnd_node_t;
> +
> +/** =========================================================================
> + * Port
> + */
> +typedef struct port_info {
> + int base_lid;
> + int smlid;
> + int link_speed_supported;
> + int link_speed_enabled;
> + int link_speed_active;
> + int port_state;
> + int phys_state;
> + int link_down_def_state;
> + int mkey_prot_bits;
> + int lmc;
> + int neighbor_mtu;
> + int smsl;
> + int init_type;
> + int vl_capability;
> + int vl_high_limit;
> + int vl_arb_high_cap;
> + int vl_arb_low_cap;
> + int init_reply;
> + int mtu_cap;
> + int vl_stall_count;
> + int hoq_lifetime;
> + int oper_vls;
> + int partition_enforce_in;
> + int partition_enforce_out;
> + int filter_raw_in;
> + int filter_raw_out;
> + int mkey_violations;
> + int pkey_violations;
> + int qkey_violations;
> + int guid_capabilities;
> + int client_rereg;
> + int subnet_timeout;
> + int response_time_val;
> + int local_phys_error;
> + int overrun_error;
> + int max_credit_hint;
> + uint32_t link_round_trip;
> + int local_port;
> + int link_width_supported;
> + int link_width_enabled;
> + int link_width_active;
> + int diag_code;
> + int mkey_lease;
> + uint32_t capability_mask;
> + uint64_t mkey;
> + uint64_t gid_prefix;
> +} ibnd_port_info_t;
> +
> +typedef struct port {
> + uint64_t guid;
> + int portnum;
> + int ext_portnum; /* optional if != 0 external port num */
> + ibnd_node_t *node; /* node this port belongs to */
> + ibnd_port_info_t info;
> + struct port *remoteport; /* null if SMA, or does not exist */
> +} ibnd_port_t;
> +
> +
> +/** =========================================================================
> + * Chassis data
> + */
> +typedef struct chassis {
> + struct chassis *next;
> + uint64_t chassisguid;
> + int chassisnum;
> +
> + /* generic grouping by SystemImageGUID */
> + int nodecount;
> + ibnd_node_t *nodes;
> +
> + /* specific to voltaire type nodes */
> +#define SPINES_MAX_NUM 12
> +#define LINES_MAX_NUM 36
> + ibnd_node_t *spinenode[SPINES_MAX_NUM + 1];
> + ibnd_node_t *linenode[LINES_MAX_NUM + 1];
> +} ibnd_chassis_t;
> +
> +/** =========================================================================
> + * Fabric
> + * Main fabric object which is returned and represents the data discovered
> + */
> +typedef struct ib_fabric {
> + /* the node the discover was initiated from
> + * "from" parameter in ibnd_discover_fabric
> + * or by default the node you ar running on
> + */
> + ibnd_node_t *from_node;
> + /* NULL term list of all nodes in the fabric */
> + ibnd_node_t *nodes;
> + /* NULL terminated list of all chassis found in the fabric */
> + ibnd_chassis_t *chassis;
> + int maxhops_discovered;
> +} ibnd_fabric_t;
> +
> +
> +/** =========================================================================
> + * Initialization (fabric operations)
> + */
> +void ibnd_debug(int i);
> +void ibnd_show_progress(int i);
> +
> +ibnd_fabric_t *ibnd_discover_fabric(char *dev_name, int dev_port,
> + int timeout_ms, ib_portid_t *from, int hops);
> + /**
> + * dev_name: (required) local device name to use to access the fabric
> + * dev_port: (required) local device port to use to access the fabric
> + * timeout_ms: (required) gives the timeout for a _SINGLE_ query on
> + * the fabric. So if there are mutiple nodes not
> + * responding this may result in a lengthy delay.
> + * from: (optional) specify the node to start scanning from.
> + * If NULL start from the node we are running on.
> + * hops: (optional) Specify how much of the fabric to traverse.
> + * negative value == scan entire fabric
> + */
> +void ibnd_destroy_fabric(ibnd_fabric_t *fabric);
> +
> +/** =========================================================================
> + * Node operations
> + */
> +ibnd_node_t *ibnd_find_node_guid(ibnd_fabric_t *fabric, uint64_t guid);
> +ibnd_node_t *ibnd_find_node_dr(ibnd_fabric_t *fabric, char *dr_str);
> +ibnd_node_t *ibnd_update_node(ibnd_node_t *node);
> +
> +typedef void (*ibnd_iter_node_func_t)(ibnd_node_t *node, void *user_data);
> +void ibnd_iter_nodes(ibnd_fabric_t *fabric,
> + ibnd_iter_node_func_t func,
> + void *user_data);
> +void ibnd_iter_nodes_type(ibnd_fabric_t *fabric,
> + ibnd_iter_node_func_t func,
> + ibnd_node_type_t node_type,
> + void *user_data);
> +
> +/** =========================================================================
> + * Str convert functions
> + */
> +char *ibnd_linkwidth_str(int link_width);
> +char *ibnd_linkstate_str(int link_state);
> +char *ibnd_physstate_str(int phys_state);
> +const char *ibnd_node_type_str(ibnd_node_t *node);
> +const char *ibnd_node_type_str_short(ibnd_node_t *node);
> +char *ibnd_linkspeed_str(int link_speed, int data_rate);
> + /* if data_rate == 0 use "SDR", "DDR", etc. */
> + /* if data_rate == 1 use "2.5 Gbps", "5.0 Gbps", etc. */
> +
> +/** =========================================================================
> + * Chassis queries
> + */
> +uint64_t ibnd_get_chassis_guid(ibnd_fabric_t *fabric, unsigned char chassisnum);
> +char *ibnd_get_chassis_type(ibnd_node_t *node);
> +char *ibnd_get_chassis_slot_str(ibnd_node_t *node, char *str, size_t size);
> +
> +int ibnd_is_xsigo_guid(uint64_t guid);
> +int ibnd_is_xsigo_tca(uint64_t guid);
> +int ibnd_is_xsigo_hca(uint64_t guid);
> +
> +#endif /* _IBNETDISC_H_ */
[snip...]
> diff --git a/infiniband-diags/libibnetdisc/src/ibnetdisc.c b/infiniband-diags/libibnetdisc/src/ibnetdisc.c
> new file mode 100644
> index 0000000..29f691c
> --- /dev/null
> +++ b/infiniband-diags/libibnetdisc/src/ibnetdisc.c
> @@ -0,0 +1,871 @@
> +/*
> + * Copyright (c) 2004-2007 Voltaire Inc. All rights reserved.
> + * Copyright (c) 2007 Xsigo Systems Inc. All rights reserved.
> + * Copyright (c) 2008 Lawrence Livermore National Laboratory
> + *
> + * 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 <infiniband/umad.h>
> +#include <infiniband/mad.h>
> +
> +#include <infiniband/ibnetdisc.h>
> +#include <complib/cl_nodenamemap.h>
> +
> +#include "internal.h"
> +#include "chassis.h"
> +
> +static int timeout_ms = 2000;
> +static int show_progress = 0;
> +
> +static char *linkwidth_str[] = {
> + "??",
> + "1x",
> + "4x",
> + "??",
> + "8x",
> + "??",
> + "??",
> + "??",
> + "12x"
> +};
> +
> +static char *linkspeed_str[] = {
> + "???",
> + "SDR",
> + "DDR",
> + "???",
> + "QDR"
> +};
> +
> +static char *linkspeed_datarate_str[] = {
> + "???",
> + "2.5 Gbps",
> + "5.0 Gbps",
> + "???",
> + "10.0 Gbps"
> +};
> +
> +static char *linkstate_str[] = {
> + "No State",
> + "Down",
> + "Init",
> + "Armed",
> + "Active"
> +};
> +
> +static char *physstate_str[] = {
> + "No State",
> + "Sleep",
> + "Polling",
> + "Disabled",
> + "PortConfigTraining",
> + "LinkUp",
> + "LinkErrorRecovery",
> + "Phy Test"
> +};
> +
> +char *
> +ibnd_linkwidth_str(int link_width)
> +{
> + if (link_width > 8)
> + return linkwidth_str[0];
> + else
> + return linkwidth_str[link_width];
> +}
> +
> +char *
> +ibnd_linkspeed_str(int link_speed, int data_rate)
> +{
> + if (link_speed > 4)
> + return linkspeed_str[0];
> + else if (data_rate)
> + return linkspeed_datarate_str[link_speed];
> + else
> + return linkspeed_str[link_speed];
> +}
> +char *
> +ibnd_linkstate_str(int link_state)
> +{
> + if (link_state > 4)
> + return linkstate_str[0];
> + else
> + return linkstate_str[link_state];
> +}
> +
> +char *
> +ibnd_physstate_str(int phys_state)
> +{
> + if (phys_state > 7)
> + return physstate_str[0];
> + else
> + return physstate_str[phys_state];
> +}
> +
> +void
> +decode_port_info(void * rcv_buf, ibnd_port_info_t *pi)
> +{
> + mad_decode_field(rcv_buf, IB_PORT_LID_F, &pi->base_lid);
> + mad_decode_field(rcv_buf, IB_PORT_SMLID_F, &pi->smlid);
> +
> + mad_decode_field(rcv_buf, IB_PORT_LINK_SPEED_SUPPORTED_F, &pi->link_speed_supported);
> + mad_decode_field(rcv_buf, IB_PORT_LINK_SPEED_ENABLED_F, &pi->link_speed_enabled);
> + mad_decode_field(rcv_buf, IB_PORT_LINK_SPEED_ACTIVE_F, &pi->link_speed_active);
> +
> + mad_decode_field(rcv_buf, IB_PORT_LOCAL_PORT_F, &pi->local_port);
> + mad_decode_field(rcv_buf, IB_PORT_LINK_WIDTH_SUPPORTED_F, &pi->link_width_supported);
> + mad_decode_field(rcv_buf, IB_PORT_LINK_WIDTH_ENABLED_F, &pi->link_width_enabled);
> +
> + mad_decode_field(rcv_buf, IB_PORT_LINK_WIDTH_ACTIVE_F, &pi->link_width_active);
> +
> + mad_decode_field(rcv_buf, IB_PORT_DIAG_F, &pi->diag_code);
> + mad_decode_field(rcv_buf, IB_PORT_MKEY_LEASE_F, &pi->mkey_lease);
> + mad_decode_field(rcv_buf, IB_PORT_CAPMASK_F, &pi->capability_mask);
> + mad_decode_field(rcv_buf, IB_PORT_MKEY_F, &pi->mkey);
> + mad_decode_field(rcv_buf, IB_PORT_GID_PREFIX_F, &pi->gid_prefix);
> +
> + mad_decode_field(rcv_buf, IB_PORT_STATE_F, &pi->port_state);
> + mad_decode_field(rcv_buf, IB_PORT_PHYS_STATE_F, &pi->phys_state);
> +
> + mad_decode_field(rcv_buf, IB_PORT_LINK_DOWN_DEF_F, &pi->link_down_def_state);
> + mad_decode_field(rcv_buf, IB_PORT_MKEY_PROT_BITS_F, &pi->mkey_prot_bits);
> +
> + mad_decode_field(rcv_buf, IB_PORT_LMC_F, &pi->lmc);
> + mad_decode_field(rcv_buf, IB_PORT_NEIGHBOR_MTU_F, &pi->neighbor_mtu);
> + mad_decode_field(rcv_buf, IB_PORT_SMSL_F, &pi->smsl);
> + mad_decode_field(rcv_buf, IB_PORT_INIT_TYPE_F, &pi->init_type);
> +
> + mad_decode_field(rcv_buf, IB_PORT_VL_CAP_F, &pi->vl_capability);
> + mad_decode_field(rcv_buf, IB_PORT_VL_HIGH_LIMIT_F, &pi->vl_high_limit);
> + mad_decode_field(rcv_buf, IB_PORT_VL_ARBITRATION_HIGH_CAP_F, &pi->vl_arb_high_cap);
> + mad_decode_field(rcv_buf, IB_PORT_VL_ARBITRATION_LOW_CAP_F, &pi->vl_arb_low_cap);
> +
> + mad_decode_field(rcv_buf, IB_PORT_INIT_TYPE_REPLY_F, &pi->init_reply);
> + mad_decode_field(rcv_buf, IB_PORT_MTU_CAP_F, &pi->mtu_cap);
> + mad_decode_field(rcv_buf, IB_PORT_VL_STALL_COUNT_F, &pi->vl_stall_count);
> + mad_decode_field(rcv_buf, IB_PORT_HOQ_LIFE_F, &pi->hoq_lifetime);
> + mad_decode_field(rcv_buf, IB_PORT_OPER_VLS_F, &pi->oper_vls);
> + mad_decode_field(rcv_buf, IB_PORT_PART_EN_INB_F, &pi->partition_enforce_in);
> + mad_decode_field(rcv_buf, IB_PORT_PART_EN_OUTB_F, &pi->partition_enforce_out);
> + mad_decode_field(rcv_buf, IB_PORT_FILTER_RAW_INB_F, &pi->filter_raw_in);
> + mad_decode_field(rcv_buf, IB_PORT_FILTER_RAW_OUTB_F, &pi->filter_raw_out);
> + mad_decode_field(rcv_buf, IB_PORT_MKEY_VIOL_F, &pi->mkey_violations);
> + mad_decode_field(rcv_buf, IB_PORT_PKEY_VIOL_F, &pi->pkey_violations);
> + mad_decode_field(rcv_buf, IB_PORT_QKEY_VIOL_F, &pi->qkey_violations);
> +
> + mad_decode_field(rcv_buf, IB_PORT_GUID_CAP_F, &pi->guid_capabilities);
> +
> + mad_decode_field(rcv_buf, IB_PORT_CLIENT_REREG_F, &pi->client_rereg);
> + mad_decode_field(rcv_buf, IB_PORT_SUBN_TIMEOUT_F, &pi->subnet_timeout);
> + mad_decode_field(rcv_buf, IB_PORT_RESP_TIME_VAL_F, &pi->response_time_val);
> + mad_decode_field(rcv_buf, IB_PORT_LOCAL_PHYS_ERR_F, &pi->local_phys_error);
> + mad_decode_field(rcv_buf, IB_PORT_OVERRUN_ERR_F, &pi->overrun_error);
> + mad_decode_field(rcv_buf, IB_PORT_MAX_CREDIT_HINT_F, &pi->max_credit_hint);
> + mad_decode_field(rcv_buf, IB_PORT_LINK_ROUND_TRIP_F, &pi->link_round_trip);
> +}
> +
> +static int
> +get_port_info(struct ibnd_fabric *fabric, struct ibnd_port *port,
> + int portnum, ib_portid_t *portid)
> +{
> + char portinfo[64];
> + void *pi = portinfo;
> +
> + port->port.portnum = portnum;
> +
> + if (!smp_query_via(pi, portid, IB_ATTR_PORT_INFO, portnum, timeout_ms,
> + fabric->ibmad_port))
> + return -1;
> +
> + decode_port_info(pi, &port->port.info);
> +
> + IBND_DEBUG("portid %s portnum %d: base lid %d state %d physstate %d %s %s\n",
> + portid2str(portid), portnum, port->port.info.base_lid, port->port.info.port_state,
> + port->port.info.phys_state, ibnd_linkwidth_str(port->port.info.link_width_active),
> + ibnd_linkspeed_str(port->port.info.link_speed_active, 0));
> + return 1;
Maybe better to use '0' as successful status (similar to another
functions like query_node_info())?
> +}
> +
> +static void
> +decode_node_info(void * rcv_buf, ibnd_node_info_t *ni)
> +{
> + mad_decode_field(rcv_buf, IB_NODE_BASE_VERS_F, &ni->base_ver);
> + mad_decode_field(rcv_buf, IB_NODE_CLASS_VERS_F, &ni->class_ver);
> + mad_decode_field(rcv_buf, IB_NODE_TYPE_F, &ni->type);
> + mad_decode_field(rcv_buf, IB_NODE_NPORTS_F, &ni->numports);
> + mad_decode_field(rcv_buf, IB_NODE_SYSTEM_GUID_F, &ni->sysimgguid);
> + mad_decode_field(rcv_buf, IB_NODE_GUID_F, &ni->nodeguid);
> + mad_decode_field(rcv_buf, IB_NODE_PORT_GUID_F, &ni->nodeportguid);
> + mad_decode_field(rcv_buf, IB_NODE_PARTITION_CAP_F, &ni->partition_cap);
> + mad_decode_field(rcv_buf, IB_NODE_DEVID_F, &ni->devid);
> + mad_decode_field(rcv_buf, IB_NODE_REVISION_F, &ni->revision);
> + mad_decode_field(rcv_buf, IB_NODE_LOCAL_PORT_F, &ni->localport);
> + mad_decode_field(rcv_buf, IB_NODE_VENDORID_F, &ni->vendid);
> +}
> +
> +/*
> + * Returns -1 if error.
> + */
> +static int
> +query_node_info(struct ibnd_fabric *fabric, struct ibnd_node *node, ib_portid_t *portid)
> +{
> + char nodeinfo[64];
> + void *ni = nodeinfo;
> + if (!smp_query_via(ni, portid, IB_ATTR_NODE_INFO, 0, timeout_ms,
> + fabric->ibmad_port))
> + return -1;
> + decode_node_info(ni, &(node->node.info));
> + return (0);
> +}
> +
> +/*
> + * Returns 0 if non switch node is found, 1 if switch is found, -1 if error.
> + */
> +static int
> +query_node(struct ibnd_fabric *fabric, struct ibnd_node *inode,
> + struct ibnd_port *iport, ib_portid_t *portid)
> +{
> + char portinfo[64];
> + void *pi = portinfo;
> + char switchinfo[64];
> + void *si = switchinfo;
> + ibnd_node_t *node = &(inode->node);
> + ibnd_port_t *port = &(iport->port);
> + void *nd = inode->node.nodedesc;
> +
> + if (query_node_info(fabric, inode, portid))
> + return -1;
> +
> + port->portnum = node->info.localport;
> + port->guid = node->info.nodeportguid;
> +
> + if (!smp_query_via(nd, portid, IB_ATTR_NODE_DESC, 0, timeout_ms,
> + fabric->ibmad_port))
> + return -1;
> +
> + if (!smp_query_via(pi, portid, IB_ATTR_PORT_INFO, 0, timeout_ms,
> + fabric->ibmad_port))
> + return -1;
> + decode_port_info(pi, &port->info);
> +
> + if (node->info.type != IBND_SWITCH_NODE)
> + return 0;
> +
> + node->smalid = port->info.base_lid;
> + node->smalmc = port->info.lmc;
> +
> + /* after we have the sma information find out the real PortInfo for this port */
> + if (!smp_query_via(pi, portid, IB_ATTR_PORT_INFO, node->info.localport, timeout_ms,
> + fabric->ibmad_port))
> + return -1;
> + decode_port_info(pi, &port->info);
> +
> + if (!smp_query_via(si, portid, IB_ATTR_SWITCH_INFO, 0, timeout_ms,
> + fabric->ibmad_port))
> + node->sw_info.smaenhsp0 = 0; /* assume base SP0 */
> + else
> + mad_decode_field(si, IB_SW_ENHANCED_PORT0_F, &node->sw_info.smaenhsp0);
Somehow indentation is broken here.
> +
> + IBND_DEBUG("portid %s: got switch node %" PRIx64 " '%s'\n",
> + portid2str(portid), node->info.nodeguid, node->nodedesc);
> + return 1;
Same about return status.
> +}
> +
> +static int
> +add_port_to_dpath(ib_dr_path_t *path, int nextport)
> +{
> + if (path->cnt+2 >= sizeof(path->p))
> + return -1;
> + ++path->cnt;
> + path->p[path->cnt] = nextport;
> + return path->cnt;
> +}
> +
> +static int
> +extend_dpath(struct ibnd_fabric *f, ib_dr_path_t *path, int nextport)
> +{
> + int rc = add_port_to_dpath(path, nextport);
> + if ((rc != -1) && (path->cnt > f->fabric.maxhops_discovered))
> + f->fabric.maxhops_discovered = path->cnt;
> + return (rc);
> +}
> +
> +static void
> +dump_endnode(ib_portid_t *path, char *prompt,
> + struct ibnd_node *node, struct ibnd_port *port)
> +{
> + if (!show_progress)
> + return;
> +
> + printf("%s -> %s %s {%016" PRIx64 "} portnum %d base lid %d-%d\"%s\"\n",
> + portid2str(path), prompt,
> + ibnd_node_type_str((ibnd_node_t *)node),
> + node->node.info.nodeguid,
> + node->node.info.type == IBND_SWITCH_NODE ? 0 : port->port.portnum,
> + port->port.info.base_lid, port->port.info.base_lid + (1 << port->port.info.lmc) - 1,
> + node->node.nodedesc);
> +}
> +
> +static struct ibnd_node *
> +find_existing_node(struct ibnd_fabric *fabric, struct ibnd_node *new)
> +{
> + int hash = HASHGUID(new->node.info.nodeguid) % HTSZ;
> + struct ibnd_node *node;
> +
> + for (node = fabric->nodestbl[hash]; node; node = node->htnext)
> + if (node->node.info.nodeguid == new->node.info.nodeguid)
> + return node;
> +
> + return NULL;
> +}
> +
> +ibnd_node_t *
> +ibnd_find_node_guid(ibnd_fabric_t *fabric, uint64_t guid)
> +{
> + struct ibnd_fabric *f = CONV_FABRIC_INTERNAL(fabric);
> + int hash = HASHGUID(guid) % HTSZ;
> + struct ibnd_node *node;
> +
> + for (node = f->nodestbl[hash]; node; node = node->htnext)
> + if (node->node.info.nodeguid == guid)
> + return (ibnd_node_t *)node;
> +
> + return NULL;
> +}
> +
> +ibnd_node_t *
> +ibnd_update_node(ibnd_node_t *node)
> +{
> + char portinfo[64];
> + void *pi = portinfo;
> + ibnd_port_info_t port0_info;
> + char switchinfo[64];
> + void *si = switchinfo;
> + void *nd = node->nodedesc;
> + int p = 0;
> + struct ibnd_fabric *f = CONV_FABRIC_INTERNAL(node->fabric);
> + struct ibnd_node *n = CONV_NODE_INTERNAL(node);
> +
> + if (query_node_info(f, n, &(n->node.path_portid)))
> + return (NULL);
> +
> + if (!smp_query_via(nd, &(n->node.path_portid), IB_ATTR_NODE_DESC, 0, timeout_ms,
> + f->ibmad_port))
> + return (NULL);
> +
> + /* update all the port info's */
> + for (p = 1; p >= n->node.info.numports; p++) {
> + get_port_info(f, CONV_PORT_INTERNAL(n->node.ports[p]), p, &(n->node.path_portid));
> + }
> +
> + if (n->node.info.type != IBND_SWITCH_NODE)
> + goto done;
> +
> + if (!smp_query_via(pi, &(n->node.path_portid), IB_ATTR_PORT_INFO, 0, timeout_ms,
> + f->ibmad_port))
> + return (NULL);
> + decode_port_info(pi, &port0_info);
> +
> + n->node.smalid = port0_info.base_lid;
> + n->node.smalmc = port0_info.lmc;
> +
> + if (!smp_query_via(si, &(n->node.path_portid), IB_ATTR_SWITCH_INFO, 0, timeout_ms,
> + f->ibmad_port))
> + node->sw_info.smaenhsp0 = 0; /* assume base SP0 */
> + else
> + mad_decode_field(si, IB_SW_ENHANCED_PORT0_F, &n->node.sw_info.smaenhsp0);
> +
> +done:
> + return (node);
> +}
> +
> +ibnd_node_t *
> +ibnd_find_node_dr(ibnd_fabric_t *fabric, char *dr_str)
> +{
> + struct ibnd_fabric *f = CONV_FABRIC_INTERNAL(fabric);
> + int i = 0;
> + ibnd_node_t *rc = f->fabric.from_node;
> + ib_dr_path_t path;
> +
> + if (str2drpath(&path, dr_str, 0, 0) == -1) {
> + return (NULL);
> + }
> +
> + for (i = 0; i <= path.cnt; i++) {
> + ibnd_port_t *remote_port = NULL;
> + if (path.p[i] == 0)
> + continue;
> + if (!rc->ports)
> + return (NULL);
> +
> + remote_port = rc->ports[path.p[i]]->remoteport;
> + if (!remote_port)
> + return (NULL);
> +
> + rc = remote_port->node;
> + }
> +
> + return (rc);
> +}
> +
> +static void
> +add_to_nodeguid_hash(struct ibnd_node *node, struct ibnd_node *hash[])
> +{
> + int hash_idx = HASHGUID(node->node.info.nodeguid) % HTSZ;
> +
> + node->htnext = hash[hash_idx];
> + hash[hash_idx] = node;
> +}
> +
> +static void
> +add_to_portguid_hash(struct ibnd_port *port, struct ibnd_port *hash[])
> +{
> + int hash_idx = HASHGUID(port->port.guid) % HTSZ;
> +
> + port->htnext = hash[hash_idx];
> + hash[hash_idx] = port;
> +}
> +
> +static void
> +add_to_type_list(struct ibnd_node*node, struct ibnd_fabric *fabric)
> +{
> + switch (node->node.info.type) {
> + case IBND_CA_NODE:
> + node->type_next = fabric->ch_adapters;
> + fabric->ch_adapters = node;
> + break;
> + case IBND_SWITCH_NODE:
> + node->type_next = fabric->switches;
> + fabric->switches = node;
> + break;
> + case IBND_ROUTER_NODE:
> + node->type_next = fabric->routers;
> + fabric->routers = node;
> + break;
> + }
> +}
> +
> +static void
> +add_to_nodedist(struct ibnd_node *node, struct ibnd_fabric *fabric)
> +{
> + int dist = node->node.dist;
> + if (node->node.info.type != IBND_SWITCH_NODE)
> + dist = MAXHOPS; /* special Ca list */
> +
> + node->dnext = fabric->nodesdist[dist];
> + fabric->nodesdist[dist] = node;
> +}
> +
> +
> +static struct ibnd_node *
> +create_node(struct ibnd_fabric *fabric, struct ibnd_node *temp, ib_portid_t *path, int dist)
> +{
> + struct ibnd_node *node;
> +
> + node = malloc(sizeof(*node));
> + if (!node) {
> + IBPANIC("OOM: node creation failed\n");
> + return NULL;
> + }
> +
> + memcpy(node, temp, sizeof(*node));
> + node->node.dist = dist;
> + node->node.path_portid = *path;
> + node->node.fabric = (ibnd_fabric_t *)fabric;
> +
> + add_to_nodeguid_hash(node, fabric->nodestbl);
> +
> + /* add this to the all nodes list */
> + node->node.next = fabric->fabric.nodes;
> + fabric->fabric.nodes = (ibnd_node_t *)node;
> +
> + add_to_type_list(node, fabric);
> + add_to_nodedist(node, fabric);
> +
> + return node;
> +}
> +
> +static struct ibnd_port *
> +find_existing_port_node(struct ibnd_node *node, struct ibnd_port *port)
> +{
> + if (port->port.portnum > node->node.info.numports || node->node.ports == NULL )
> + return (NULL);
> +
> + return (CONV_PORT_INTERNAL(node->node.ports[port->port.portnum]));
> +}
> +
> +static struct ibnd_port *
> +add_port_to_node(struct ibnd_fabric *fabric, struct ibnd_node *node, struct ibnd_port *temp)
> +{
> + struct ibnd_port *port;
> +
> + port = malloc(sizeof(*port));
> + if (!port)
> + return NULL;
> +
> + memcpy(port, temp, sizeof(*port));
> + port->port.node = (ibnd_node_t *)node;
> + port->port.ext_portnum = 0;
> +
> + if (node->node.ports == NULL) {
> + node->node.ports = calloc(sizeof(*node->node.ports), node->node.info.numports + 1);
> + if (!node->node.ports) {
> + IBND_ERROR("Failed to allocate the ports array\n");
> + return (NULL);
> + }
> + }
> +
> + node->node.ports[temp->port.portnum] = (ibnd_port_t *)port;
> +
> + add_to_portguid_hash(port, fabric->portstbl);
> + return port;
> +}
> +
> +static void
> +link_ports(struct ibnd_node *node, struct ibnd_port *port,
> + struct ibnd_node *remotenode, struct ibnd_port *remoteport)
> +{
> + IBND_DEBUG("linking: 0x%" PRIx64 " %p->%p:%u and 0x%" PRIx64 " %p->%p:%u\n",
> + node->node.info.nodeguid, node, port, port->port.portnum,
> + remotenode->node.info.nodeguid, remotenode,
> + remoteport, remoteport->port.portnum);
> + if (port->port.remoteport)
> + port->port.remoteport->remoteport = NULL;
> + if (remoteport->port.remoteport)
> + remoteport->port.remoteport->remoteport = NULL;
> + port->port.remoteport = (ibnd_port_t *)remoteport;
> + remoteport->port.remoteport = (ibnd_port_t *)port;
> +}
> +
> +static int
> +get_remote_node(struct ibnd_fabric *fabric, struct ibnd_node *node, struct ibnd_port *port, ib_portid_t *path,
> + int portnum, int dist)
> +{
> + struct ibnd_node node_buf;
> + struct ibnd_port port_buf;
> + struct ibnd_node *remotenode, *oldnode;
> + struct ibnd_port *remoteport, *oldport;
> +
> + memset(&node_buf, 0, sizeof(node_buf));
> + memset(&port_buf, 0, sizeof(port_buf));
> +
> + IBND_DEBUG("handle node %p port %p:%d dist %d\n", node, port, portnum, dist);
> + if (port->port.info.phys_state != 5) /* LinkUp */
> + return -1;
> +
> + if (extend_dpath(fabric, &path->drpath, portnum) < 0)
> + return -1;
> +
> + if (query_node(fabric, &node_buf, &port_buf, path) < 0) {
> + IBWARN("NodeInfo on %s failed, skipping port",
> + portid2str(path));
> + path->drpath.cnt--; /* restore path */
> + return -1;
> + }
> +
> + oldnode = find_existing_node(fabric, &node_buf);
> + if (oldnode)
> + remotenode = oldnode;
> + else if (!(remotenode = create_node(fabric, &node_buf, path, dist + 1)))
> + IBPANIC("no memory");
> +
> + oldport = find_existing_port_node(remotenode, &port_buf);
> + if (oldport) {
> + remoteport = oldport;
> + } else if (!(remoteport = add_port_to_node(fabric, remotenode, &port_buf)))
> + IBPANIC("no memory");
> +
> + dump_endnode(path, oldnode ? "known remote" : "new remote",
> + remotenode, remoteport);
> +
> + link_ports(node, port, remotenode, remoteport);
> +
> + path->drpath.cnt--; /* restore path */
> + return 0;
> +}
> +
> +static void *
> +ibnd_init_port(char *dev_name, int dev_port)
> +{
> + int mgmt_classes[2] = {IB_SMI_CLASS, IB_SMI_DIRECT_CLASS};
> +
> + /* Crank up the mad lib */
> + return (mad_rpc_open_port(dev_name, dev_port, mgmt_classes, 2));
> +}
> +
> +ibnd_fabric_t *
> +ibnd_discover_fabric(char *dev_name, int dev_port, int timeout_ms,
> + ib_portid_t *from, int hops)
> +{
> + struct ibnd_fabric *fabric = NULL;
> + ib_portid_t my_portid = {0};
> + struct ibnd_node node_buf;
> + struct ibnd_port port_buf;
> + struct ibnd_node *node;
> + struct ibnd_port *port;
> + int i;
> + int dist = 0;
> + ib_portid_t *path;
> + int max_hops = MAXHOPS-1; /* default find everything */
> +
> + /* if not everything how much? */
> + if (hops >= 0) {
> + max_hops = hops;
> + }
> +
> + /* If not specified start from "my" port */
> + if (!from) {
> + from = &my_portid;
> + }
> +
> + fabric = malloc(sizeof(*fabric));
> +
> + if (!fabric) {
> + IBPANIC("OOM: failed to malloc ibnd_fabric_t\n");
> + return (NULL);
> + }
> +
> + memset(fabric, 0, sizeof(*fabric));
> +
> + fabric->ibmad_port = ibnd_init_port(dev_name, dev_port);
> + if (!fabric->ibmad_port) {
> + IBPANIC("OOM: failed to open \"%s\" port %d\n",
> + dev_name, dev_port);
> + goto error;
> + }
> +
> + IBND_DEBUG("from %s\n", portid2str(from));
> +
> + memset(&node_buf, 0, sizeof(node_buf));
> + memset(&port_buf, 0, sizeof(port_buf));
> +
> + if (query_node(fabric, &node_buf, &port_buf, from) < 0) {
> + IBWARN("can't reach node %s\n", portid2str(from));
> + goto error;
> + }
> +
> + node = create_node(fabric, &node_buf, from, 0);
> + if (!node)
> + goto error;
> +
> + fabric->fabric.from_node = (ibnd_node_t *)node;
> +
> + port = add_port_to_node(fabric, node, &port_buf);
> + if (!port)
> + IBPANIC("out of memory");
> +
> + if (node->node.info.type != IBND_SWITCH_NODE &&
> + get_remote_node(fabric, node, port, from, node->node.info.localport, 0) < 0)
> + return ((ibnd_fabric_t *)fabric);
> +
> + for (dist = 0; dist <= max_hops; dist++) {
> +
> + for (node = fabric->nodesdist[dist]; node; node = node->dnext) {
> +
> + path = &node->node.path_portid;
> +
> + IBND_DEBUG("dist %d node %p\n", dist, node);
> + dump_endnode(path, "processing", node, port);
> +
> + for (i = 1; i <= node->node.info.numports; i++) {
> + if (i == node->node.info.localport)
> + continue;
> +
> + if (get_port_info(fabric, &port_buf, i, path) < 0) {
> + IBWARN("can't reach node %s port %d", portid2str(path), i);
> + continue;
> + }
> +
> + port = find_existing_port_node(node, &port_buf);
> + if (port)
> + continue;
> +
> + port = add_port_to_node(fabric, node, &port_buf);
> + if (!port)
> + IBPANIC("out of memory");
> +
> + /* If switch, set port GUID to node port GUID */
> + if (node->node.info.type == IBND_SWITCH_NODE)
> + port->port.guid = node->node.info.nodeportguid;
> +
> + get_remote_node(fabric, node, port, path, i, dist);
> + }
> + }
> + }
> +
> + fabric->fabric.chassis = group_nodes(fabric);
> +
> + return ((ibnd_fabric_t *)fabric);
> +error:
> + free(fabric);
> + return (NULL);
> +}
> +
> +static void
> +destroy_node(struct ibnd_node *node)
> +{
> + int p = 0;
> +
> + for (p = 0; p <= node->node.info.numports; p++) {
> + free(node->node.ports[p]);
> + }
> + free(node->node.ports);
> + free(node);
> +}
> +
> +void
> +ibnd_destroy_fabric(ibnd_fabric_t *fabric)
> +{
> + struct ibnd_fabric *f = CONV_FABRIC_INTERNAL(fabric);
> + int dist = 0;
> + struct ibnd_node *node = NULL;
> + struct ibnd_node *next = NULL;
> + ibnd_chassis_t *ch, *ch_next;
> +
> + ch = f->first_chassis;
> + while (ch) {
> + ch_next = ch->next;
> + free(ch);
> + ch = ch_next;
> + }
> + for (dist = 0; dist <= MAXHOPS; dist++) {
> + node = f->nodesdist[dist];
> + while (node) {
> + next = node->dnext;
> + destroy_node(node);
> + node = next;
> + }
> + }
> + if (f->ibmad_port)
> + mad_rpc_close_port(f->ibmad_port);
> + free(f);
> +}
> +
> +void
> +ibnd_debug(int i)
> +{
> + if (i) {
> + ibdebug++;
> + madrpc_show_errors(1);
> + umad_debug(i);
> + } else {
> + ibdebug = 0;
> + madrpc_show_errors(0);
> + umad_debug(0);
> + }
> +}
> +
> +void
> +ibnd_show_progress(int i)
> +{
> + show_progress = i;
> +}
> +
> +const char*
> +ibnd_node_type_str(ibnd_node_t *node)
> +{
> + switch(node->info.type) {
> + case IBND_CA_NODE: return "Ca";
> + case IBND_SWITCH_NODE: return "Switch";
> + case IBND_ROUTER_NODE: return "Router";
> + }
> + return "??";
> +}
> +
> +const char*
> +ibnd_node_type_str_short(ibnd_node_t *node)
> +{
> + switch(node->info.type) {
> + case IBND_SWITCH_NODE: return "SW";
> + case IBND_CA_NODE: return "CA";
> + case IBND_ROUTER_NODE: return "RT";
> + }
> + return "??";
> +}
> +
> +
> +void
> +ibnd_iter_nodes(ibnd_fabric_t *fabric,
> + ibnd_iter_node_func_t func,
> + void *user_data)
> +{
> + ibnd_node_t *cur = NULL;
> +
> + for (cur = fabric->nodes; cur; cur = cur->next) {
> + func(cur, user_data);
> + }
> +}
> +
> +
> +void
> +ibnd_iter_nodes_type(ibnd_fabric_t *fabric,
> + ibnd_iter_node_func_t func,
> + ibnd_node_type_t node_type,
> + void *user_data)
> +{
> + struct ibnd_fabric *f = CONV_FABRIC_INTERNAL(fabric);
> + struct ibnd_node *list = NULL;
> + struct ibnd_node *cur = NULL;
> +
> + switch (node_type) {
> + case IBND_SWITCH_NODE:
> + list = f->switches;
> + break;
> + case IBND_CA_NODE:
> + list = f->ch_adapters;
> + break;
> + case IBND_ROUTER_NODE:
> + list = f->routers;
> + break;
> + default:
> + IBND_DEBUG("Invalid node_type specified %d\n", node_type);
> + break;
> + }
> +
> + for (cur = list; cur; cur = cur->type_next) {
> + func((ibnd_node_t *)cur, user_data);
> + }
> +}
> +
> diff --git a/infiniband-diags/libibnetdisc/src/internal.h b/infiniband-diags/libibnetdisc/src/internal.h
> new file mode 100644
> index 0000000..89f238f
> --- /dev/null
> +++ b/infiniband-diags/libibnetdisc/src/internal.h
> @@ -0,0 +1,82 @@
> +/*
> + * Copyright (c) 2008 Lawrence Livermore National Laboratory
> + *
> + * 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 the internal data structures.
> + */
> +
> +#ifndef _INTERNAL_H_
> +#define _INTERNAL_H_
> +
> +#include <infiniband/ibnetdisc.h>
> +
> +struct ibnd_node {
> + /* This member MUST BE FIRST */
> + ibnd_node_t node;
> +
> + /* internal use only */
> + unsigned char ch_found;
> + struct ibnd_node *htnext; /* hash table list */
> + struct ibnd_node *dnext; /* nodesdist next */
> + struct ibnd_node *type_next; /* next based on type */
> +};
> +#define CONV_NODE_INTERNAL(node) ((struct ibnd_node *)node)
> +
> +struct ibnd_port {
> + /* This member MUST BE FIRST */
> + ibnd_port_t port;
> +
> + /* internal use only */
> + struct ibnd_port *htnext;
> +};
> +#define CONV_PORT_INTERNAL(port) ((struct ibnd_port *)port)
> +
> +struct ibnd_fabric {
> + /* This member MUST BE FIRST */
> + ibnd_fabric_t fabric;
> +
> + /* internal use only */
> + void *ibmad_port;
> + struct ibnd_node *nodestbl[HTSZ];
> + struct ibnd_port *portstbl[HTSZ];
> + struct ibnd_node *nodesdist[MAXHOPS+1];
> + ibnd_chassis_t *first_chassis;
> + ibnd_chassis_t *current_chassis;
> + ibnd_chassis_t *last_chassis;
> + struct ibnd_node *switches;
> + struct ibnd_node *ch_adapters;
> + struct ibnd_node *routers;
> +};
> +#define CONV_FABRIC_INTERNAL(fabric) ((struct ibnd_fabric *)fabric)
Why should we hide this internal data so hard?
Maybe we can use a single structures, to mark those fields (in comment)
as "for internal use" - somebody may want to use it.
> +
> +#endif /* _INTERNAL_H_ */
> diff --git a/infiniband-diags/libibnetdisc/src/libibnetdisc.map b/infiniband-diags/libibnetdisc/src/libibnetdisc.map
> new file mode 100644
> index 0000000..5e8c315
> --- /dev/null
> +++ b/infiniband-diags/libibnetdisc/src/libibnetdisc.map
> @@ -0,0 +1,27 @@
> +IBNETDISC_1.0 {
> + global:
> + ibnd_debug;
> + ibnd_show_progress;
> + ibnd_discover_fabric;
> + ibnd_cache_fabric;
> + ibnd_read_fabric;
> + ibnd_destroy_fabric;
> + ibnd_find_node_guid;
> + ibnd_update_node;
Where is ibnd_update_node() useful (in public API)?
> + ibnd_find_node_dr;
> + ibnd_linkwidth_str;
> + ibnd_linkspeed_str;
> + ibnd_node_type_str;
> + ibnd_node_type_str_short;
> + ibnd_is_xsigo_guid;
> + ibnd_is_xsigo_tca;
> + ibnd_is_xsigo_hca;
> + ibnd_get_chassis_guid;
> + ibnd_get_chassis_type;
> + ibnd_get_chassis_slot_str;
> + ibnd_linkstate_str;
> + ibnd_physstate_str;
> + ibnd_iter_nodes;
> + ibnd_iter_nodes_type;
> + local: *;
> +};
Sasha
More information about the general
mailing list